def authenticated_user(aaai_services): from Acquire.Crypto import PrivateKey, OTP from Acquire.Client import User, Service, Wallet username = str(uuid.uuid4()) password = PrivateKey.random_passphrase() result = User.register(username=username, password=password, identity_url="identity") otpsecret = result["otpsecret"] otp = OTP(otpsecret) # now log the user in user = User(username=username, identity_url="identity", auto_logout=False) result = user.request_login() assert (type(result) is dict) wallet = Wallet() wallet.send_password(url=result["login_url"], username=username, password=password, otpcode=otp.generate(), remember_password=False, remember_device=False) user.wait_for_login() assert (user.is_logged_in()) return user
def test_service_object(tmpdir_factory): bucket = tmpdir_factory.mktemp("test_service") push_testing_objstore(bucket) push_is_running_service() try: service = Service.create(service_type="identity", service_url="identity") assert(service.uid() is not None) assert(service.uid().startswith("STAGE1")) service.create_stage2(service_uid="Z9-Z8", response=service.uid()) assert(service.is_identity_service()) assert(not service.should_refresh_keys()) assert(service.is_unlocked()) assert(not service.is_locked()) passphrase = PrivateKey.random_passphrase() data = service.to_data(passphrase) service2 = IdentityService.from_data(data, passphrase) assert(service2.uid() == service.uid()) assert(service2.is_unlocked()) assert(not service2.is_locked()) assert(service2.is_identity_service()) assert(service.canonical_url() == service2.canonical_url()) assert(not service2.should_refresh_keys()) keys = service.dump_keys() keys = service.load_keys(keys) assert(keys[service.private_key().fingerprint()] == service.private_key()) assert(keys[service.private_certificate().fingerprint()] == service.private_certificate()) service.refresh_keys() assert(service.last_key_update() > service2.last_key_update()) assert(service.last_certificate().public_key() == service2.public_certificate()) assert(service.last_key() == service2.private_key()) except: pop_is_running_service() pop_testing_objstore() raise pop_is_running_service() pop_testing_objstore()
def __init__(self, drive_uid=None, file_uid=None): """Create a new ChunkUploader that uploads the specified file to the specified drive """ self._drive_uid = None self._file_uid = None self._chunk_idx = None self._service = None if drive_uid is not None: self._drive_uid = str(drive_uid) self._file_uid = str(file_uid) from Acquire.Crypto import PrivateKey as _PrivateKey self._secret = _PrivateKey.random_passphrase()
def challenge_service(self, service): """Send a challenge to the passed service, returning the actual service returned. This will only pass if our copy of the service matches us with the copy returned from the actual service. This verifies that there is a real service sitting at that URL, and that we have the right keys and certs """ from Acquire.Crypto import PrivateKey as _PrivateKey from Acquire.ObjectStore import bytes_to_string as _bytes_to_string from Acquire.Service import Service as _Service challenge = _PrivateKey.random_passphrase() pubkey = service.public_key() encrypted_challenge = pubkey.encrypt(challenge) args = {"challenge": _bytes_to_string(encrypted_challenge), "fingerprint": pubkey.fingerprint()} if service.uid().startswith("STAGE"): # we cannot call using the service directly, as it is # not yet fully constructed from Acquire.Service import get_this_service as _get_this_service from Acquire.Service import call_function as _call_function this_service = _get_this_service(need_private_access=True) result = _call_function(service_url=service.service_url(), function=None, args=args, args_key=service.public_key(), response_key=this_service.private_key(), public_cert=service.public_certificate()) else: result = service.call_function(function=None, args=args) if result["response"] != challenge: raise PermissionError( "Failure of the service %s to correctly respond " "to the challenge!" % service) return _Service.from_data(result["service_info"])
def __init__(self, drive_uid=None, file_uid=None): """Create a new ChunkDowloader that downloads the specified file from the specified drive """ self._uid = None self._drive_uid = None self._file_uid = None self._service = None self._next_index = None self._last_filename = None self._downloaded_filename = None self._FILE = None if drive_uid is not None: self._drive_uid = str(drive_uid) self._file_uid = str(file_uid) from Acquire.Crypto import PrivateKey as _PrivateKey self._secret = _PrivateKey.random_passphrase() from Acquire.ObjectStore import create_uid as _create_uid self._uid = _create_uid(short_uid=True)
import pytest from Acquire.Service import call_function from Acquire.Client import User, Wallet from Acquire.Identity import Authorisation from Acquire.Crypto import OTP, PrivateKey _wallet_password = PrivateKey.random_passphrase() @pytest.mark.parametrize("username, password", [("testuser", "ABCdef12345"), ("something", "!!DDerfld31"), ("someone", "%$(F*Dj4jij43 kdfjdk")]) def test_login(username, password, aaai_services, tmpdir): # register the new user result = User.register(username=username, password=password, identity_url="identity") assert(type(result) is dict) otpsecret = result["otpsecret"] otp = OTP(otpsecret) user = User(username=username, identity_url="identity", auto_logout=False) result = user.request_login()
def aaai_services(tmpdir_factory): """This function creates mocked versions of all of the main services of the system, returning the json describing each service as a dictionary (which is passed to the test functions as the fixture) """ from Acquire.Identity import Authorisation from Acquire.Crypto import PrivateKey, OTP from Acquire.Service import call_function, Service _services = {} _services["registry"] = tmpdir_factory.mktemp("registry") _services["identity"] = tmpdir_factory.mktemp("identity") _services["accounting"] = tmpdir_factory.mktemp("accounting") _services["access"] = tmpdir_factory.mktemp("access") _services["storage"] = tmpdir_factory.mktemp("storage") _services["userdata"] = tmpdir_factory.mktemp("userdata") _services["compute"] = tmpdir_factory.mktemp("compute") _services["hugs"] = tmpdir_factory.mktemp("hugs") wallet_dir = tmpdir_factory.mktemp("wallet") wallet_password = PrivateKey.random_passphrase() _set_services(_services, wallet_dir, wallet_password) password = PrivateKey.random_passphrase() args = {"password": password} responses = {} os.environ["SERVICE_PASSWORD"] = "******" os.environ["STORAGE_COMPARTMENT"] = str(_services["userdata"]) args["canonical_url"] = "registry" args["service_type"] = "registry" args["registry_uid"] = "Z9-Z9" # UID of testing registry response = call_function("registry", function="admin/setup", args=args) registry_service = Service.from_data(response["service"]) registry_otp = OTP(OTP.extract_secret(response["provisioning_uri"])) registry_user = _login_admin("registry", "admin", password, registry_otp) responses["registry"] = { "service": registry_service, "user": registry_user, "response": response, } assert registry_service.registry_uid() == registry_service.uid() service_uids = [registry_service.uid()] args["canonical_url"] = "identity" args["service_type"] = "identity" response = call_function("identity", function="admin/setup", args=args) identity_service = Service.from_data(response["service"]) identity_otp = OTP(OTP.extract_secret(response["provisioning_uri"])) identity_user = _login_admin("identity", "admin", password, identity_otp) responses["identity"] = { "service": identity_service, "user": identity_user, "response": response, } assert identity_service.registry_uid() == registry_service.uid() assert identity_service.uid() not in service_uids service_uids.append(identity_service.uid()) args["canonical_url"] = "accounting" args["service_type"] = "accounting" response = call_function("accounting", function="admin/setup", args=args) accounting_service = Service.from_data(response["service"]) accounting_otp = OTP(OTP.extract_secret(response["provisioning_uri"])) accounting_user = _login_admin("accounting", "admin", password, accounting_otp) responses["accounting"] = { "service": accounting_service, "user": accounting_user, "response": response, } assert accounting_service.registry_uid() == registry_service.uid() assert accounting_service.uid() not in service_uids service_uids.append(accounting_service.uid()) args["canonical_url"] = "access" args["service_type"] = "access" response = call_function("access", function="admin/setup", args=args) responses["access"] = response access_service = Service.from_data(response["service"]) access_otp = OTP(OTP.extract_secret(response["provisioning_uri"])) access_user = _login_admin("access", "admin", password, access_otp) responses["access"] = { "service": access_service, "user": access_user, "response": response, } assert access_service.registry_uid() == registry_service.uid() assert access_service.uid() not in service_uids service_uids.append(access_service.uid()) args["canonical_url"] = "compute" args["service_type"] = "compute" response = call_function("compute", function="admin/setup", args=args) responses["compute"] = response compute_service = Service.from_data(response["service"]) compute_otp = OTP(OTP.extract_secret(response["provisioning_uri"])) compute_user = _login_admin("compute", "admin", password, compute_otp) responses["compute"] = { "service": compute_service, "user": compute_user, "response": response, } assert compute_service.registry_uid() == registry_service.uid() assert compute_service.uid() not in service_uids service_uids.append(compute_service.uid()) args["canonical_url"] = "storage" args["service_type"] = "storage" response = call_function("storage", function="admin/setup", args=args) storage_service = Service.from_data(response["service"]) storage_otp = OTP(OTP.extract_secret(response["provisioning_uri"])) storage_user = _login_admin("storage", "admin", password, storage_otp) responses["storage"] = { "service": storage_service, "user": storage_user, "response": response, } assert storage_service.registry_uid() == registry_service.uid() assert storage_service.uid() not in service_uids service_uids.append(storage_service.uid()) args["canonical_url"] = "hugs" args["service_type"] = "hugs" response = call_function("hugs", function="admin/setup", args=args) responses["hugs"] = response hugs_service = Service.from_data(response["service"]) hugs_otp = OTP(OTP.extract_secret(response["provisioning_uri"])) hugs_user = _login_admin("hugs", "admin", password, hugs_otp) responses["hugs"] = { "service": hugs_service, "user": hugs_user, "response": response, } resource = "trust_accounting_service %s" % accounting_service.uid() args = { "service_url": accounting_service.canonical_url(), "authorisation": Authorisation(user=access_user, resource=resource).to_data(), } access_service.call_function(function="admin/trust_accounting_service", args=args) responses["_services"] = _services return responses
def create(username, password, _service_uid=None, _service_public_key=None): """Create a new account with username 'username', which will be secured using the passed password. Note that this will create an account with a specified user UID, meaning that different users can have the same username. We identify the right user via the combination of username, password and OTP code. Normally the UID of the service, and the skeleton key used to encrypt the backup password are obtained directly from the service. However, when initialising a new service we must pass these directly. In those cases, pass the object using _service_uid and _service_public_key This returns a tuple of the user_uid and OTP for the newly-created account """ from Acquire.ObjectStore import create_uuid as _create_uuid from Acquire.Crypto import PrivateKey as _PrivateKey from Acquire.Crypto import PublicKey as _PublicKey from Acquire.ObjectStore import ObjectStore as _ObjectStore from Acquire.Service import get_service_account_bucket \ as _get_service_account_bucket from Acquire.ObjectStore import bytes_to_string as _bytes_to_string from Acquire.Identity import UserCredentials as _UserCredentials from Acquire.ObjectStore import get_datetime_now_to_string \ as _get_datetime_now_to_string if _service_public_key is None: from Acquire.Service import get_this_service as _get_this_service service_pubkey = _get_this_service().public_skeleton_key() assert (service_pubkey is not None) else: service_pubkey = _service_public_key if not isinstance(service_pubkey, _PublicKey): raise TypeError("The service public key must be type PublicKey") if _service_uid is None: from Acquire.Service import get_this_service \ as _get_this_service service_uid = _get_this_service(need_private_access=False).uid() else: service_uid = _service_uid # create a UID for this new user user_uid = _create_uuid() # now create the primary password for this user and use # this to encrypt the special keys for this user privkey = _PrivateKey(name="user_secret_key %s %s" % (username, user_uid)) primary_password = _PrivateKey.random_passphrase() bucket = _get_service_account_bucket() # now create the credentials used to validate a login otp = _UserCredentials.create(user_uid=user_uid, password=password, primary_password=primary_password) # create the user account user = UserAccount(username=username, user_uid=user_uid, private_key=privkey, status="active") # now save a lookup from the username to this user_uid # (many users can have the same username). Use this lookup # to hold a recovery password for this account recovery_password = _bytes_to_string( service_pubkey.encrypt(primary_password)) key = "%s/names/%s/%s" % (_user_root, user.encoded_name(), user_uid) _ObjectStore.set_string_object(bucket=bucket, key=key, string_data=recovery_password) # now save a lookup from the hashed username+password # to the user_uid, so that we can # quickly find matching user_uids (expect few people will have # exactly the same username and password). This will # save the exact time this username-password combination # was set encoded_password = _UserCredentials.hash(username=username, password=password, service_uid=service_uid) key = "%s/passwords/%s/%s" % (_user_root, encoded_password, user_uid) _ObjectStore.set_string_object( bucket=bucket, key=key, string_data=_get_datetime_now_to_string()) # finally(!) save the account itself to the object store key = "%s/uids/%s" % (_user_root, user_uid) data = user.to_data(passphrase=primary_password) _ObjectStore.set_object_from_json(bucket=bucket, key=key, data=data) # return the OTP and user_uid return (user_uid, otp)
def get_trusted_registry_service(registry_uid=None, service_uid=None, service_url=None): """Return the trusted service info for the registry with specified registry_uid, or get any trusted registry service using either 'service_uid' or 'service_url' as a starting hint to locate a suitable registry """ if service_uid is not None: # for the moment, just try to get one registry. Eventually we should # try to get several in case this one is down registry_uid = get_primary_registry_uid(service_uid) return get_trusted_registry_service(registry_uid=registry_uid) if service_url is not None: if service_url.find(".") != -1: # try the main acquire registry first return get_trusted_registry_service(registry_uid="a0-a0") else: # this must be testing... return get_trusted_registry_service(registry_uid="Z9-Z9") if registry_uid is None: raise PermissionError( "You must specify one of registry_uid, service_uid " "or service_url") from Acquire.Service import get_trusted_service as _get_trusted_service try: registry_service = _get_trusted_service(service_uid=registry_uid, autofetch=False) except: registry_service = None if registry_service is not None: if not registry_service.is_registry_service(): from Acquire.Service import ServiceError raise ServiceError("The requested service (%s) for %s is NOT a " "registry service!" % (registry_service, registry_uid)) if registry_service.uid() != registry_uid: from Acquire.Service import ServiceError raise ServiceError( "Disagreement of UID (%s) is NOT the right registry service!" % registry_service) # everything is ok - we have seen this registry before return registry_service # boostrapping from Acquire.Registry import get_registry_details \ as _get_registry_details details = _get_registry_details(registry_uid) from Acquire.Service import call_function as _call_function from Acquire.Service import Service as _Service from Acquire.Crypto import get_private_key as _get_private_key from Acquire.Crypto import PrivateKey as _PrivateKey from Acquire.Crypto import PublicKey as _PublicKey from Acquire.ObjectStore import bytes_to_string as _bytes_to_string from Acquire.ObjectStore import string_to_bytes as _string_to_bytes privkey = _get_private_key(key="registry") pubkey = _PublicKey.from_data(details["public_key"]) pubcert = _PublicKey.from_data(details["public_certificate"]) # ask the registry to return to us their latest details - use # a challenge-response to make sure that the response is # properly returned challenge = _PrivateKey.random_passphrase() encrypted_challenge = _bytes_to_string(pubkey.encrypt(challenge)) args = { "challenge": encrypted_challenge, "fingerprint": pubkey.fingerprint() } result = _call_function(service_url=details["canonical_url"], function=None, args=args, args_key=pubkey, response_key=privkey, public_cert=pubcert) if result["response"] != challenge: from Acquire.Service import ServiceError raise ServiceError( "The requested service (%s) failed to respond to the challenge!" % registry_service) registry_service = _Service.from_data(result["service_info"]) if not registry_service.is_registry_service(): from Acquire.Service import ServiceError raise ServiceError( "The requested service (%s) is NOT a registry service!" % registry_service) if registry_service.uid() != details["uid"]: from Acquire.Service import ServiceError raise ServiceError( "Disagreement of UID (%s) is NOT the right registry service!" % registry_service) # ok - we've got the registry - add this to the set of # trusted services so that we don't need to bootstrap from # the registry details again from Acquire.Service import trust_service as _trust_service _trust_service(registry_service) return registry_service
def __init__(self, location=None, user=None, aclrule=None, expires_datetime=None): """Construct a PAR for the specified location, authorised by the passed user, giving permissions according to the passed 'aclrule' (default is ACLRule.reader()). The passed 'expires_datetime' is the time at which this PAR will expire (by default within 24 hours) """ self._location = None self._uid = None self._expires_datetime = None if location is None: return from Acquire.Client import Location as _Location if not isinstance(location, _Location): raise TypeError("The location must be type Location") if location.is_null(): return from Acquire.Client import User as _User if not isinstance(user, _User): raise TypeError("The user must be type User") if not user.is_logged_in(): raise PermissionError("The passed User must be logged in!") from Acquire.Client import ACLRule as _ACLRule if aclrule is None: aclrule = _ACLRule.reader() elif not isinstance(aclrule, _ACLRule): raise TypeError("The aclrule must be type ACLRule") if expires_datetime is None: from Acquire.ObjectStore import get_datetime_future \ as _get_datetime_future expires_datetime = _get_datetime_future(days=1) else: from Acquire.ObjectStore import datetime_to_datetime \ as _datetime_to_datetime expires_datetime = _datetime_to_datetime(expires_datetime) self._location = location self._expires_datetime = expires_datetime self._aclrule = aclrule from Acquire.Client import Authorisation as _Authorisation auth = _Authorisation(user=user, resource="create_par %s" % self.fingerprint()) from Acquire.Crypto import PrivateKey as _PrivateKey self._secret = _PrivateKey.random_passphrase() args = { "authorisation": auth.to_data(), "par": self.to_data(), "secret": self._secret } service = location.service() result = service.call_function(function="create_par", args=args) self._set_uid(result["par_uid"])
old_config = service_key.decrypt(string_to_bytes(service_info["config"])) old_config = json.loads(old_config) keep = True else: while True: password = getpass.getpass( prompt="Please enter the service primary password: "******"Please enter the password again: ") if password == password2: break print("Passwords not equal - please try again") service_salt = PrivateKey.random_passphrase() password = Hash.multi_md5(password, service_salt) old_config = None service_key = PrivateKey() service_key_data = service_key.to_data(passphrase=password) with open(config_file, "r") as FILE: config = load(FILE, Loader=Loader) if old_config is not None: if old_config["service"] != config["service"]: for key in config["service"].keys(): if old_config["service"][key] != config["service"][key]: print( "\nDisagree key = %s\n%s\n%s" %