def from_data(data, password=None): """Deserialise this object from the passed data. This will only deserialise the private key, private certificate, and OTP if a valid password and passcode is supplied """ service = Service() if password: # get the private info... service._privkey = _PrivateKey.from_data(data["private_key"], password) service._privcert = _PrivateKey.from_data( data["private_certificate"], password) service._otpsecret = _string_to_bytes(data["otpsecret"]) service._admin_password = _string_to_bytes(data["admin_password"]) else: service._privkey = None service._privcert = None service._otpsecret = None service._uuid = data["uuid"] service._service_type = data["service_type"] service._service_url = data["service_url"] service._canonical_url = service._service_url service._pubkey = _PublicKey.from_data(data["public_key"]) service._pubcert = _PublicKey.from_data(data["public_certificate"]) if service.is_identity_service(): from Acquire.Identity import IdentityService as _IdentityService return _IdentityService(service) elif service.is_access_service(): from Acquire.Access import AccessService as _AccessService return _AccessService(service) elif service.is_accounting_service(): from Acquire.Accounting import AccountingService \ as _AccountingService return _AccountingService(service) else: return service
def test_keys(): privkey = PrivateKey() pubkey = privkey.public_key() message = "Hello World" sig = privkey.sign(message.encode("utf-8")) pubkey.verify(sig, message.encode("utf-8")) c = pubkey.encrypt(message.encode("utf-8")) m = privkey.decrypt(c).decode("utf-8") assert (m == message) privkey2 = PrivateKey() sig2 = privkey2.sign(message.encode("utf-8")) with pytest.raises(SignatureVerificationError): pubkey.verify(sig2, message.encode("utf-8")) bytes = privkey.bytes("testPass32") PrivateKey.read_bytes(bytes, "testPass32") privkey.write("test.pem", "testPass32") PrivateKey.read("test.pem", "testPass32") bytes = pubkey.bytes() pubkey2 = PublicKey.read_bytes(bytes) assert (bytes == pubkey2.bytes()) long_message = str([random.getrandbits(8) for _ in range(4096)]).encode("utf-8") c = pubkey.encrypt(long_message) m = privkey.decrypt(c) assert (m == long_message) os.unlink("test.pem") data = pubkey.to_data() pubkey2 = PublicKey.from_data(data) assert (pubkey.bytes() == pubkey2.bytes()) data = privkey.to_data("testPass33") privkey2 = PrivateKey.from_data(data, "testPass33") assert (privkey == privkey2)
def from_data(data, passphrase=None): """Return a OSPar constructed from the passed json-deserliased dictionary Args: data (dict): JSON-deserialised dictionary from which to create OSPar Returns: OSPar: OSPar object created from dict """ if data is None or len(data) == 0: return OSPar() from Acquire.ObjectStore import string_to_datetime \ as _string_to_datetime from Acquire.ObjectStore import string_to_bytes \ as _string_to_bytes par = OSPar() par._url = _string_to_bytes(data["url"]) par._key = data["key"] par._uid = data["uid"] if par._key is not None: par._key = str(par._key) par._expires_datetime = _string_to_datetime(data["expires_datetime"]) par._is_readable = data["is_readable"] par._is_writeable = data["is_writeable"] if "service_url" in data: par._service_url = data["service_url"] if "privkey" in data: if passphrase is not None: from Acquire.Crypto import PrivateKey as _PrivateKey par._privkey = _PrivateKey.from_data(data["privkey"], passphrase) # note that we don't load the driver details as this # is stored and loaded separately on the service return par
def from_data(data, passphrase, mangleFunction=None): """Return a UserAccount constructed from the passed data (dictionary) """ user = UserAccount() if data is not None and len(data) > 0: from Acquire.Crypto import PrivateKey as _PrivateKey user._username = data["username"] user._status = data["status"] user._uid = data["uid"] user._privkey = _PrivateKey.from_data( data=data["private_key"], passphrase=passphrase, mangleFunction=mangleFunction) return user
def get_service_account_bucket(testing_dir=None): """This function logs into the object store account of the service account. Accessing the object store means being able to access all resources and which can authorise the creation of access all resources on the object store. Obviously this is a powerful account, so only log into it if you need it!!! The login information should not be put into a public repository or stored in plain text. In this case, the login information is held in an environment variable (which should be encrypted or hidden in some way...) """ from Acquire.Service import assert_running_service as \ _assert_running_service _assert_running_service() # read the password for the secret key from the filesystem try: with open("secret_key", "r") as FILE: password = FILE.readline()[0:-1] except: password = None # we must be in testing mode... from Acquire.ObjectStore import use_testing_object_store_backend as \ _use_testing_object_store_backend # see if this is running in testing mode... global _current_testing_objstore if testing_dir: _current_testing_objstore = testing_dir return _use_testing_object_store_backend(testing_dir) elif _current_testing_objstore: return _use_testing_object_store_backend(_current_testing_objstore) if password is None: from Acquire.Service import ServiceAccountError raise ServiceAccountError( "You need to supply login credentials via the 'secret_key' " "file, and 'SECRET_KEY' and 'SECRET_CONFIG' environment " "variables! %s" % testing_dir) secret_key = _os.getenv("SECRET_KEY") if secret_key is None: from Acquire.Service import ServiceAccountError raise ServiceAccountError( "You must supply the password used to unlock the configuration " "key in the 'SECRET_KEY' environment variable") try: secret_key = _json.loads(secret_key) except Exception as e: from Acquire.Service import ServiceAccountError raise ServiceAccountError( "Unable to decode valid JSON from the secret key: %s" % str(e)) # use the password to decrypt the SECRET_KEY in the config try: from Acquire.Crypto import PrivateKey as _PrivateKey secret_key = _PrivateKey.from_data(secret_key, password) except Exception as e: from Acquire.Service import ServiceAccountError raise ServiceAccountError( "Unable to open the private SECRET_KEY using the password " "supplied in the 'secret_key' file: %s" % str(e)) config = _os.getenv("SECRET_CONFIG") if config is None: from Acquire.Service import ServiceAccountError raise ServiceAccountError( "You must supply the encrypted config in teh 'SECRET_CONFIG' " "environment variable!") try: from Acquire.ObjectStore import string_to_bytes as _string_to_bytes config = secret_key.decrypt(_string_to_bytes(config)) except Exception as e: from Acquire.Service import ServiceAccountError raise ServiceAccountError( "Cannot decrypt the 'SECRET_CONFIG' with the 'SECRET_KEY'. Are " "you sure that the configuration has been set up correctly? %s " % str(e)) # use the secret_key to decrypt the config in SECRET_CONFIG try: config = _json.loads(config) except Exception as e: from Acquire.Service import ServiceAccountError raise ServiceAccountError( "Unable to decode valid JSON from the config: %s" % str(e)) # get info from this config access_data = config["LOGIN"] bucket_data = config["BUCKET"] # save the service password to the environment _os.environ["SERVICE_PASSWORD"] = config["PASSWORD"] # save any other decrypted config data to environment variables for key in config.keys(): if key not in ["LOGIN", "BUCKET", "PASSWORD"]: _os.environ[key] = config[key] # we have OCI login details, so make sure that we are using # the OCI object store backend from Acquire.ObjectStore import use_oci_object_store_backend as \ _use_oci_object_store_backend _use_oci_object_store_backend() # now login and create/load the bucket for this account try: from ._oci_account import OCIAccount as _OCIAccount account_bucket = _OCIAccount.create_and_connect_to_bucket( access_data, bucket_data["compartment"], bucket_data["bucket"]) except Exception as e: from Acquire.Service import ServiceAccountError raise ServiceAccountError( "Error connecting to the service account: %s" % str(e)) return account_bucket
def validate_password(user_uid, username, device_uid, secrets, password, otpcode, remember_device): """Validate that the passed password and one-time-code are valid. If they are, then return a tuple of the UserAccount of the unlocked user, the OTP that is used to generate secrets, and the device_uid of the login device If 'remember_device' is True and 'device_uid' is None, then this creates a new OTP for the login device, which is returned, and a new device_uid for that device. The password needed to match this device is a MD5 of the normal user password. """ from Acquire.Crypto import PrivateKey as _PrivateKey from Acquire.Crypto import OTP as _OTP from Acquire.ObjectStore import string_to_bytes as _string_to_bytes privkey = _PrivateKey.from_data(data=secrets["private_key"], passphrase=password) # decrypt and validate the OTP code data = _string_to_bytes(secrets["otpsecret"]) otpsecret = privkey.decrypt(data) otp = _OTP(secret=otpsecret) otp.verify(code=otpcode, once_only=True) # everything is ok - we can load the user account via the # decrypted primary password primary_password = _string_to_bytes(secrets["primary_password"]) primary_password = privkey.decrypt(primary_password) from Acquire.ObjectStore import ObjectStore as _ObjectStore from Acquire.Service import get_service_account_bucket \ as _get_service_account_bucket data = None secrets = None key = "%s/uids/%s" % (_user_root, user_uid) bucket = _get_service_account_bucket() try: data = _ObjectStore.get_object_from_json(bucket=bucket, key=key) except: pass if data is None: from Acquire.Identity import UserValidationError raise UserValidationError( "Unable to validate user as no account data is present!") from Acquire.Identity import UserAccount as _UserAccount user = _UserAccount.from_data(data=data, passphrase=primary_password) if user.uid() != user_uid: from Acquire.Identity import UserValidationError raise UserValidationError( "Unable to validate user as mismatch in user_uids!") if device_uid is None and remember_device: # create a new OTP that is unique for this device from Acquire.ObjectStore import create_uuid as _create_uuid from Acquire.Client import Credentials as _Credentials device_uid = _create_uuid() device_password = _Credentials.encode_device_uid( encoded_password=password, device_uid=device_uid) otp = UserCredentials.create(user_uid=user_uid, password=device_password, primary_password=primary_password, device_uid=device_uid) # now save a lookup so that we can find the user_uid from # the username and device-specific password encoded_password = UserCredentials.hash( username=username, password=device_password) key = "%s/passwords/%s/%s" % (_user_root, encoded_password, user_uid) from Acquire.ObjectStore import get_datetime_now_to_string \ as _get_datetime_now_to_string _ObjectStore.set_string_object( bucket=bucket, key=key, string_data=_get_datetime_now_to_string()) return {"user": user, "otp": otp, "device_uid": device_uid}
service_file = "service.json" if os.path.exists(service_file): with open(service_file, "r") as FILE: service_info = json.load(FILE) service_salt = service_info["salt"] while True: password = getpass.getpass( prompt="Please enter the service primary password: "******"key"], passphrase=password) break except: print("Password incorrect. Try again.") 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
def login_to_service_account(testing_dir=None): """This function logs into the object store account of the service account. Accessing the object store means being able to access all resources and which can authorise the creation of access all resources on the object store. Obviously this is a powerful account, so only log into it if you need it!!! The login information should not be put into a public repository or stored in plain text. In this case, the login information is held in an environment variable (which should be encrypted or hidden in some way...) """ # read the password for the secret key from the filesystem try: with open("secret_key", "r") as FILE: password = FILE.readline()[0:-1] except: password = None # we must be in testing mode... from Acquire.ObjectStore import use_testing_object_store_backend as \ _use_testing_object_store_backend # see if this is running in testing mode... global _current_testing_objstore if testing_dir: _current_testing_objstore = testing_dir return _use_testing_object_store_backend(testing_dir) elif _current_testing_objstore: return _use_testing_object_store_backend(_current_testing_objstore) if password is None: raise ServiceAccountError( "You need to supply login credentials via the 'secret_key' " "file, and 'SECRET_KEY' and 'SECRET_CONFIG' environment " "variables! %s" % testing_dir) # use the password to decrypt the SECRET_KEY in the config secret_key = _PrivateKey.from_data(_json.loads(_os.getenv("SECRET_KEY")), password) # use the secret_key to decrypt the config in SECRET_CONFIG config = _json.loads( secret_key.decrypt(_string_to_bytes( _os.getenv("SECRET_CONFIG"))).decode("utf-8")) # get info from this config access_data = config["LOGIN"] bucket_data = config["BUCKET"] # save the service password to the environment _os.environ["SERVICE_PASSWORD"] = config["PASSWORD"] # we have OCI login details, so make sure that we are using # the OCI object store backend from Acquire.ObjectStore import use_oci_object_store_backend as \ _use_oci_object_store_backend _use_oci_object_store_backend() # now login and create/load the bucket for this account try: from ._oci_account import OCIAccount as _OCIAccount account_bucket = _OCIAccount.create_and_connect_to_bucket( access_data, bucket_data["compartment"], bucket_data["bucket"]) except Exception as e: raise ServiceAccountError( "Error connecting to the service account: %s" % str(e)) return account_bucket