def _login(store, packages=None, acls=None, channels=None, save=True): print('Enter your Ubuntu One SSO credentials.') email = input('Email: ') password = getpass.getpass('Password: '******'Second-factor auth: ') store.login( email, password, one_time_password=one_time_password, acls=acls, packages=packages, channels=channels, save=save) # Continue if agreement and namespace conditions are met. _check_dev_agreement_and_namespace_statuses(store) except storeapi.errors.InvalidCredentialsError: return _fail_login(storeapi.constants.INVALID_CREDENTIALS) except storeapi.errors.StoreAuthenticationError: return _fail_login(storeapi.constants.AUTHENTICATION_ERROR) except storeapi.errors.StoreAccountInformationError: return _fail_login(storeapi.constants.ACCOUNT_INFORMATION_ERROR) except storeapi.errors.NeedTermsSignedError as e: return _fail_login(e.message) else: print() echo.info('Login successful.') return True
def validate( snap_name: str, validations: List[str], revoke: bool = False, key: Optional[str] = None, ): """Generate, sign and upload validation assertions.""" # Check validations format _check_validations(validations) # Need the ID of the logged in user. store_client = StoreClientCLI() account_info = store_client.get_account_information() authority_id = account_info["account_id"] # Get data for the gating snap try: snap_id = account_info["snaps"][DEFAULT_SERIES][snap_name]["snap-id"] except KeyError: raise storeapi.errors.SnapNotFoundError(snap_name=snap_name) # Then, for each requested validation, generate assertion for validation in validations: gated_snap, rev = validation.split("=", 1) echo.info(f"Getting details for {gated_snap}") # The Info API is not authed, so it cannot see private snaps. try: approved_data = store_client.cpi.get_info(gated_snap) approved_snap_id = approved_data.snap_id except storeapi.errors.SnapNotFoundError: approved_snap_id = gated_snap assertion_payload = { "type": "validation", "authority-id": authority_id, "series": DEFAULT_SERIES, "snap-id": snap_id, "approved-snap-id": approved_snap_id, "approved-snap-revision": rev, "timestamp": datetime.utcnow().isoformat() + "Z", "revoked": "false", } if revoke: assertion_payload["revoked"] = "true" assertion = _sign_assertion(validation, assertion_payload, key, "validations") # Save assertion to a properly named file fname = f"{snap_name}-{gated_snap}-r{rev}.assertion" with open(fname, "wb") as f: f.write(assertion) store_client.push_assertion(snap_id, assertion, endpoint="validations")
def _sign_assertion(snap_name, assertion, key, endpoint): cmdline = ['snap', 'sign'] if key: cmdline += ['-k', key] snap_sign = Popen( cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) data = json.dumps(assertion).encode('utf8') echo.info('Signing {} assertion for {}'.format(endpoint, snap_name)) assertion, err = snap_sign.communicate(input=data) if snap_sign.returncode != 0: err = err.decode() raise storeapi.errors.StoreAssertionError( endpoint=endpoint, snap_name=snap_name, error=err) return assertion
def _sign_assertion(snap_name, assertion, key, endpoint): cmdline = ['snap', 'sign'] if key: cmdline += ['-k', key] snap_sign = Popen( cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) data = json.dumps(assertion).encode('utf8') echo.info('Signing {} assertion for {}'.format(endpoint, snap_name)) assertion, err = snap_sign.communicate(input=data) if snap_sign.returncode != 0: err = err.decode('ascii', errors='replace') raise storeapi.errors.StoreAssertionError( endpoint=endpoint, snap_name=snap_name, error=err) return assertion
def validate(snap_name, validations, revoke=False, key=None): """Generate, sign and upload validation assertions.""" # Check validations format _check_validations(validations) store = storeapi.StoreClient() # Need the ID of the logged in user. with _requires_login(): account_info = store.get_account_information() authority_id = account_info["account_id"] # Get data for the gating snap release = storeapi.constants.DEFAULT_SERIES try: snap_id = account_info["snaps"][release][snap_name]["snap-id"] except KeyError: raise storeapi.errors.SnapNotFoundError(snap_name) # Then, for each requested validation, generate assertion for validation in validations: gated_name, rev = validation.split("=", 1) echo.info("Getting details for {}".format(gated_name)) approved_data = store.cpi.get_info(gated_name) assertion = { "type": "validation", "authority-id": authority_id, "series": release, "snap-id": snap_id, "approved-snap-id": approved_data.snap_id, "approved-snap-revision": rev, "timestamp": datetime.utcnow().isoformat() + "Z", "revoked": "false", } if revoke: assertion["revoked"] = "true" assertion = _sign_assertion(validation, assertion, key, "validations") # Save assertion to a properly named file fname = "{}-{}-r{}.assertion".format(snap_name, gated_name, rev) with open(fname, "wb") as f: f.write(assertion) store.push_assertion(snap_id, assertion, endpoint="validations")
def validate(snap_name, validations, revoke=False, key=None): """Generate, sign and upload validation assertions.""" # Check validations format _check_validations(validations) store = storeapi.StoreClient() # Need the ID of the logged in user. with _requires_login(): account_info = store.get_account_information() authority_id = account_info['account_id'] # Get data for the gating snap release = storeapi.constants.DEFAULT_SERIES try: snap_id = account_info['snaps'][release][snap_name]['snap-id'] except KeyError: raise storeapi.errors.SnapNotFoundError(snap_name) # Then, for each requested validation, generate assertion for validation in validations: gated_name, rev = validation.split('=', 1) echo.info('Getting details for {}'.format(gated_name)) approved_data = store.cpi.get_package(gated_name, 'stable') assertion = { 'type': 'validation', 'authority-id': authority_id, 'series': release, 'snap-id': snap_id, 'approved-snap-id': approved_data['snap_id'], 'approved-snap-revision': rev, 'timestamp': datetime.utcnow().isoformat() + 'Z', 'revoked': "false" } if revoke: assertion['revoked'] = "true" assertion = _sign_assertion(validation, assertion, key, 'validations') # Save assertion to a properly named file fname = '{}-{}-r{}.assertion'.format(snap_name, gated_name, rev) with open(fname, 'wb') as f: f.write(assertion) store.push_assertion(snap_id, assertion, endpoint='validations')
def _login(store, packages=None, acls=None, channels=None, save=True): print('Enter your Ubuntu One e-mail address and password.\n' 'If you do not have an Ubuntu One account, you can create one at ' 'https://dashboard.snapcraft.io/openid/login') email = input('Email: ') password = getpass.getpass('Password: '******'Second-factor auth: ') store.login(email, password, one_time_password=one_time_password, acls=acls, packages=packages, channels=channels, save=save) # Continue if agreement and namespace conditions are met. _check_dev_agreement_and_namespace_statuses(store) except storeapi.errors.InvalidCredentialsError: return _fail_login(storeapi.constants.INVALID_CREDENTIALS) except storeapi.errors.StoreAuthenticationError: return _fail_login(storeapi.constants.AUTHENTICATION_ERROR) except storeapi.errors.StoreAccountInformationError: return _fail_login(storeapi.constants.ACCOUNT_INFORMATION_ERROR) except storeapi.errors.NeedTermsSignedError as e: return _fail_login(e.message) else: print() echo.info('Login successful.') return True