def create_authority_roles(roles, owner, plugin_title): """ Creates all of the necessary authority roles. :param roles: :return: """ role_objs = [] for r in roles: role = role_service.get_by_name(r['name']) if not role: role = role_service.create( r['name'], password=r['password'], description="Auto generated role for {0}".format(plugin_title), username=r['username']) # the user creating the authority should be able to administer it if role.username == 'admin': g.current_user.roles.append(role) role_objs.append(role) # create an role for the owner and assign it owner_role = role_service.get_by_name(owner) if not owner_role: owner_role = role_service.create( owner, description="Auto generated role based on owner: {0}".format(owner) ) role_objs.append(owner_role) return role_objs
def get_authority_role(ca_name): """ Attempts to get the authority role for a given ca uses current_user as a basis for accomplishing that. :param ca_name: """ if g.current_user.is_admin: return role_service.get_by_name("{0}_admin".format(ca_name)) else: return role_service.get_by_name("{0}_operator".format(ca_name))
def create_certificate_roles(**kwargs): # create an role for the owner and assign it owner_role = role_service.get_by_name(kwargs['owner']) if not owner_role: owner_role = role_service.create( kwargs['owner'], description="Auto generated role based on owner: {0}".format(kwargs['owner']) ) # ensure that the authority's owner is also associated with the certificate if kwargs.get('authority'): authority_owner_role = role_service.get_by_name(kwargs['authority'].owner) return [owner_role, authority_owner_role] return [owner_role]
def create_user_roles(profile): """Creates new roles based on profile information. :param profile: :return: """ roles = [] # update their google 'roles' for group in profile['googleGroups']: role = role_service.get_by_name(group) if not role: role = role_service.create( group, description= 'This is a google group based role created by Lemur', third_party=True) if not role.third_party: role = role_service.set_third_party(role.id, third_party_status=True) roles.append(role) role = role_service.get_by_name(profile['email']) if not role: role = role_service.create(profile['email'], description='This is a user specific role', third_party=True) if not role.third_party: role = role_service.set_third_party(role.id, third_party_status=True) roles.append(role) # every user is an operator (tied to a default role) if current_app.config.get('LEMUR_DEFAULT_ROLE'): default = role_service.get_by_name( current_app.config['LEMUR_DEFAULT_ROLE']) if not default: default = role_service.create( current_app.config['LEMUR_DEFAULT_ROLE'], description='This is the default Lemur role.') if not default.third_party: role_service.set_third_party(default.id, third_party_status=True) roles.append(default) return roles
def create_certificate_roles(**kwargs): # create an role for the owner and assign it owner_role = role_service.get_by_name(kwargs['owner']) if not owner_role: owner_role = role_service.create( kwargs['owner'], description="Auto generated role based on owner: {0}".format( kwargs['owner'])) # ensure that the authority's owner is also associated with the certificate if kwargs.get('authority'): authority_owner_role = role_service.get_by_name( kwargs['authority'].owner) return [owner_role, authority_owner_role] return [owner_role]
def delete(self, pending_certificate_id, data=None): """ .. http:delete:: /pending_certificates/1 Cancel and delete a pending certificate **Example request**: .. sourcecode:: http DELETE /pending certificates/1 HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "note": "Why I am cancelling this order" } **Example response**: .. sourcecode:: http HTTP/1.1 204 No Content :reqheader Authorization: OAuth token to authenticate :statuscode 204: no error :statuscode 401: unauthenticated :statuscode 403: unauthorized :statuscode 404: pending certificate id not found :statuscode 500: internal error """ pending_cert = service.get(pending_certificate_id) if not pending_cert: return dict( message="Cannot find specified pending certificate"), 404 # allow creators if g.current_user != pending_cert.user: owner_role = role_service.get_by_name(pending_cert.owner) permission = CertificatePermission( owner_role, [x.name for x in pending_cert.roles]) if not permission.can(): return dict( message='You are not authorized to update this certificate' ), 403 if service.cancel(pending_cert, **data): service.delete(pending_cert) return ('', 204) else: # service.cancel raises exception if there was an issue, but this will ensure something # is relayed to user in case of something unexpected (unsuccessful update somehow). return dict( message= "Unexpected error occurred while trying to cancel this certificate" ), 500
def create(**kwargs): """ Creates a new authority. """ ca_name = kwargs.get("name") if get_by_name(ca_name): raise Exception(f"Authority with name {ca_name} already exists") if role_service.get_by_name(f"{ca_name}_admin") or role_service.get_by_name(f"{ca_name}_operator"): raise Exception(f"Admin and/or operator roles for authority {ca_name} already exist") body, private_key, chain, roles = mint(**kwargs) kwargs["creator"].roles = list(set(list(kwargs["creator"].roles) + roles)) kwargs["body"] = body kwargs["private_key"] = private_key kwargs["chain"] = chain if kwargs.get("roles"): kwargs["roles"] += roles else: kwargs["roles"] = roles cert = upload(**kwargs) kwargs["authority_certificate"] = cert if kwargs.get("plugin", {}).get("plugin_options", []): # encrypt the private key before persisting in DB for option in kwargs.get("plugin").get("plugin_options"): if option["name"] == "acme_private_key" and option["value"]: option["value"] = data_encrypt(option["value"]) kwargs["options"] = json.dumps(kwargs["plugin"]["plugin_options"]) authority = Authority(**kwargs) authority = database.create(authority) kwargs["creator"].authorities.append(authority) log_service.audit_log("create_authority", ca_name, "Created new authority") issuer = kwargs["plugin"]["plugin_object"] current_app.logger.warning(f"Created new authority {ca_name} with issuer {issuer.title}") metrics.send( "authority_created", "counter", 1, metric_tags=dict(owner=authority.owner) ) return authority
def _authorize(self): """ check groups and roles to confirm access. return a list of roles if ok. raise an exception on error. """ if not self.ldap_principal: return None if self.ldap_required_group: # ensure the user has the required group in their group list if self.ldap_required_group not in self.ldap_groups: return None roles = set() if self.ldap_default_role: role = role_service.get_by_name(self.ldap_default_role) if role: if not role.third_party: role = role.set_third_party(role.id, third_party_status=True) roles.add(role) # update their 'roles' role = role_service.get_by_name(self.ldap_principal) if not role: description = "auto generated role based on owner: {0}".format(self.ldap_principal) role = role_service.create(self.ldap_principal, description=description, third_party=True) if not role.third_party: role = role_service.set_third_party(role.id, third_party_status=True) roles.add(role) if not self.ldap_groups_to_roles: return roles for ldap_group_name, role_name in self.ldap_groups_to_roles.items(): role = role_service.get_by_name(role_name) if role: if ldap_group_name in self.ldap_groups: current_app.logger.debug("assigning role {0} to ldap user {1}".format(self.ldap_principal, role)) if not role.third_party: role = role_service.set_third_party(role.id, third_party_status=True) roles.add(role) return roles
def create_certificate_roles(**kwargs): # create an role for the owner and assign it owner_role = role_service.get_by_name(kwargs['owner']) if not owner_role: owner_role = role_service.create( kwargs['owner'], description="Auto generated role based on owner: {0}".format(kwargs['owner']) ) return [owner_role]
def create(**kwargs): """ Creates a new authority. """ ca_name = kwargs.get("name") if get_by_name(ca_name): raise Exception(f"Authority with name {ca_name} already exists") if role_service.get_by_name( f"{ca_name}_admin") or role_service.get_by_name( f"{ca_name}_operator"): raise Exception( f"Admin and/or operator roles for authority {ca_name} already exist" ) body, private_key, chain, roles = mint(**kwargs) kwargs["creator"].roles = list(set(list(kwargs["creator"].roles) + roles)) kwargs["body"] = body kwargs["private_key"] = private_key kwargs["chain"] = chain if kwargs.get("roles"): kwargs["roles"] += roles else: kwargs["roles"] = roles cert = upload(**kwargs) kwargs["authority_certificate"] = cert if kwargs.get("plugin", {}).get("plugin_options", []): kwargs["options"] = json.dumps(kwargs["plugin"]["plugin_options"]) authority = Authority(**kwargs) authority = database.create(authority) kwargs["creator"].authorities.append(authority) log_service.audit_log("create_authority", ca_name, "Created new authority") metrics.send("authority_created", "counter", 1, metric_tags=dict(owner=authority.owner)) return authority
def put(self, certificate_id, data=None): """ .. http:put:: /certificates/1/revoke Revoke a certificate **Example request**: .. sourcecode:: http POST /certificates/1/revoke HTTP/1.1 Host: example.com Accept: application/json, text/javascript **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { 'id': 1 } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 # allow creators if g.current_user != cert.user: owner_role = role_service.get_by_name(cert.owner) permission = CertificatePermission(owner_role, [x.name for x in cert.roles]) if not permission.can(): return dict(message='You are not authorized to revoke this certificate.'), 403 if not cert.external_id: return dict(message='Cannot revoke certificate. No external id found.'), 400 if cert.endpoints: return dict(message='Cannot revoke certificate. Endpoints are deployed with the given certificate.'), 403 plugin = plugins.get(cert.authority.plugin_name) plugin.revoke_certificate(cert, data) log_service.create(g.current_user, 'revoke_cert', certificate=cert) return dict(id=cert.id)
def delete(self, certificate_id, data=None): """ .. http:delete:: /certificates/1 Delete a certificate **Example request**: .. sourcecode:: http DELETE /certificates/1 HTTP/1.1 Host: example.com **Example response**: .. sourcecode:: http HTTP/1.1 204 OK :reqheader Authorization: OAuth token to authenticate :statuscode 204: no error :statuscode 403: unauthenticated :statuscode 404: certificate not found :statuscode 405: certificate deletion is disabled """ if not current_app.config.get("ALLOW_CERT_DELETION", False): return dict(message="Certificate deletion is disabled"), 405 cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 if cert.deleted: return dict(message="Certificate is already deleted"), 412 # allow creators if g.current_user != cert.user: owner_role = role_service.get_by_name(cert.owner) permission = CertificatePermission(owner_role, [x.name for x in cert.roles]) if not permission.can(): return ( dict(message= "You are not authorized to delete this certificate"), 403, ) service.update(certificate_id, deleted=True) log_service.create(g.current_user, "delete_cert", certificate=cert) return "Certificate deleted", 204
def run(self, password): create() user = user_service.get_by_username("lemur") if not user: if not password: sys.stdout.write( "We need to set Lemur's password to continue!\n") password = prompt_pass("Password") password1 = prompt_pass("Confirm Password") if password != password1: sys.stderr.write("[!] Passwords do not match!\n") sys.exit(1) role = role_service.get_by_name('admin') if role: sys.stdout.write( "[-] Admin role already created, skipping...!\n") else: # we create an admin role role = role_service.create( 'admin', description='this is the lemur administrator role') sys.stdout.write("[+] Created 'admin' role\n") user_service.create("lemur", password, 'lemur@nobody', True, None, [role]) sys.stdout.write( "[+] Added a 'lemur' user and added it to the 'admin' role!\n") else: sys.stdout.write( "[-] Default user has already been created, skipping...!\n") sys.stdout.write("[+] Creating expiration email notifications!\n") sys.stdout.write( "[!] Using {0} as specified by LEMUR_SECURITY_TEAM_EMAIL for notifications\n" .format("LEMUR_SECURITY_TEAM_EMAIL")) intervals = current_app.config.get( "LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS", []) sys.stdout.write( "[!] Creating {num} notifications for {intervals} days as specified by LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS\n" .format(num=len(intervals), intervals=",".join([str(x) for x in intervals]))) recipients = current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL') notification_service.create_default_expiration_notifications( "DEFAULT_SECURITY", recipients=recipients) sys.stdout.write("[/] Done!\n")
def create_certificate_roles(**kwargs): # create a role for the owner and assign it owner_role = role_service.get_or_create( kwargs["owner"], description=f"Auto generated role based on owner: {kwargs['owner']}" ) # ensure that the authority's owner is also associated with the certificate if kwargs.get("authority"): authority_owner_role = role_service.get_by_name(kwargs["authority"].owner) return [owner_role, authority_owner_role] return [owner_role]
def delete(self, pending_certificate_id, data=None): """ .. http:delete:: /pending_certificates/1 Cancel and delete a pending certificate **Example request**: .. sourcecode:: http DELETE /pending certificates/1 HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "note": "Why I am cancelling this order" } **Example response**: .. sourcecode:: http HTTP/1.1 204 No Content :reqheader Authorization: OAuth token to authenticate :statuscode 204: no error :statuscode 401: unauthenticated :statuscode 403: unauthorized :statuscode 404: pending certificate id not found :statuscode 500: internal error """ pending_cert = service.get(pending_certificate_id) if not pending_cert: return dict(message="Cannot find specified pending certificate"), 404 # allow creators if g.current_user != pending_cert.user: owner_role = role_service.get_by_name(pending_cert.owner) permission = CertificatePermission(owner_role, [x.name for x in pending_cert.roles]) if not permission.can(): return dict(message='You are not authorized to update this certificate'), 403 if service.cancel(pending_cert, **data): service.delete(pending_cert) return('', 204) else: # service.cancel raises exception if there was an issue, but this will ensure something # is relayed to user in case of something unexpected (unsuccessful update somehow). return dict(message="Unexpected error occurred while trying to cancel this certificate"), 500
def delete(self, certificate_id, data=None): """ .. http:delete:: /certificates/1 Delete a certificate **Example request**: .. sourcecode:: http DELETE /certificates/1 HTTP/1.1 Host: example.com **Example response**: .. sourcecode:: http HTTP/1.1 200 OK :reqheader Authorization: OAuth token to authenticate :statuscode 204: no error :statuscode 403: unauthenticated :statusoode 404: certificate not found """ cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 # allow creators if g.current_user != cert.user: owner_role = role_service.get_by_name(cert.owner) permission = CertificatePermission(owner_role, [x.name for x in cert.roles]) if not permission.can(): return dict( message='You are not authorized to delete this certificate' ), 403 if arrow.get(cert.not_after) > arrow.utcnow(): return dict( message= 'Certificate is still valid, only expired certificates can be deleted' ), 412 service.update(certificate_id, deleted=True) log_service.create(g.current_user, 'delete_cert', certificate=cert) return '', 204
def get(self, certificate_id): """ .. http:get:: /certificates/1/key Retrieves the private key for a given certificate **Example request**: .. sourcecode:: http GET /certificates/1/key HTTP/1.1 Host: example.com Accept: application/json, text/javascript **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "key": "-----BEGIN ...", } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 # allow creators if g.current_user != cert.user: owner_role = role_service.get_by_name(cert.owner) permission = CertificatePermission(owner_role, [x.name for x in cert.roles]) if not permission.can(): return dict( message='You are not authorized to view this key'), 403 log_service.create(g.current_user, 'key_view', certificate=cert) response = make_response(jsonify(key=cert.private_key), 200) response.headers[ 'cache-control'] = 'private, max-age=0, no-cache, no-store' response.headers['pragma'] = 'no-cache' return response
def _authorize(self): """ check groups and roles to confirm access. return a list of roles if ok. raise an exception on error. """ if not self.ldap_principal: return None if self.ldap_required_group: # ensure the user has the required group in their group list if self.ldap_required_group not in self.ldap_groups: return None roles = set() if self.ldap_default_role: role = role_service.get_by_name(self.ldap_default_role) if role: roles.add(role) # update their 'roles' role = role_service.get_by_name(self.ldap_principal) if not role: description = "auto generated role based on owner: {0}".format(self.ldap_principal) role = role_service.create(self.ldap_principal, description=description) roles.add(role) if not self.ldap_groups_to_roles: return roles for ldap_group_name, role_name in self.ldap_groups_to_roles.items(): role = role_service.get_by_name(role_name) if role: if ldap_group_name in self.ldap_groups: current_app.logger.debug("assigning role {0} to ldap user {1}".format(self.ldap_principal, role)) roles.add(role) return roles
def create_user_roles(profile): """Creates new roles based on profile information. :param profile: :return: """ roles = [] # update their google 'roles' for group in profile['googleGroups']: role = role_service.get_by_name(group) if not role: role = role_service.create(group, description='This is a google group based role created by Lemur', third_party=True) if not role.third_party: role = role_service.set_third_party(role.id, third_party_status=True) roles.append(role) role = role_service.get_by_name(profile['email']) if not role: role = role_service.create(profile['email'], description='This is a user specific role', third_party=True) if not role.third_party: role = role_service.set_third_party(role.id, third_party_status=True) roles.append(role) # every user is an operator (tied to a default role) if current_app.config.get('LEMUR_DEFAULT_ROLE'): default = role_service.get_by_name(current_app.config['LEMUR_DEFAULT_ROLE']) if not default: default = role_service.create(current_app.config['LEMUR_DEFAULT_ROLE'], description='This is the default Lemur role.') if not default.third_party: role_service.set_third_party(default.id, third_party_status=True) roles.append(default) return roles
def delete(self, certificate_id, data=None): """ .. http:delete:: /certificates/1 Delete a certificate **Example request**: .. sourcecode:: http DELETE /certificates/1 HTTP/1.1 Host: example.com **Example response**: .. sourcecode:: http HTTP/1.1 204 OK :reqheader Authorization: OAuth token to authenticate :statuscode 204: no error :statuscode 403: unauthenticated :statuscode 404: certificate not found :statuscode 405: certificate deletion is disabled """ if not current_app.config.get('ALLOW_CERT_DELETION', False): return dict(message="Certificate deletion is disabled"), 405 cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 if cert.deleted: return dict(message="Certificate is already deleted"), 412 # allow creators if g.current_user != cert.user: owner_role = role_service.get_by_name(cert.owner) permission = CertificatePermission(owner_role, [x.name for x in cert.roles]) if not permission.can(): return dict(message='You are not authorized to delete this certificate'), 403 service.update(certificate_id, deleted=True) log_service.create(g.current_user, 'delete_cert', certificate=cert) return 'Certificate deleted', 204
def get(self, certificate_id): """ .. http:get:: /certificates/1/key Retrieves the private key for a given certificate **Example request**: .. sourcecode:: http GET /certificates/1/key HTTP/1.1 Host: example.com Accept: application/json, text/javascript **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "key": "----Begin ...", } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 role = role_service.get_by_name(cert.owner) permission = ViewKeyPermission(certificate_id, getattr(role, 'name', None)) if permission.can(): response = make_response(jsonify(key=cert.private_key), 200) response.headers[ 'cache-control'] = 'private, max-age=0, no-cache, no-store' response.headers['pragma'] = 'no-cache' return response return dict(message='You are not authorized to view this key'), 403
def get(self, certificate_id): """ .. http:get:: /certificates/1/key Retrieves the private key for a given certificate **Example request**: .. sourcecode:: http GET /certificates/1/key HTTP/1.1 Host: example.com Accept: application/json, text/javascript **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "key": "-----BEGIN ..." } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 # allow creators if g.current_user != cert.user: owner_role = role_service.get_by_name(cert.owner) permission = CertificatePermission(owner_role, [x.name for x in cert.roles]) if not permission.can(): return dict(message='You are not authorized to view this key'), 403 log_service.create(g.current_user, 'key_view', certificate=cert) response = make_response(jsonify(key=cert.private_key), 200) response.headers['cache-control'] = 'private, max-age=0, no-cache, no-store' response.headers['pragma'] = 'no-cache' return response
def run(self, password): create() user = user_service.get_by_username("lemur") if not user: if not password: sys.stdout.write("We need to set Lemur's password to continue!\n") password = prompt_pass("Password") password1 = prompt_pass("Confirm Password") if password != password1: sys.stderr.write("[!] Passwords do not match!\n") sys.exit(1) role = role_service.get_by_name("admin") if role: sys.stdout.write("[-] Admin role already created, skipping...!\n") else: # we create an admin role role = role_service.create("admin", description="this is the lemur administrator role") sys.stdout.write("[+] Created 'admin' role\n") user_service.create("lemur", password, "lemur@nobody", True, None, [role]) sys.stdout.write("[+] Added a 'lemur' user and added it to the 'admin' role!\n") else: sys.stdout.write("[-] Default user has already been created, skipping...!\n") sys.stdout.write("[+] Creating expiration email notifications!\n") sys.stdout.write( "[!] Using {0} as specified by LEMUR_SECURITY_TEAM_EMAIL for notifications\n".format( "LEMUR_SECURITY_TEAM_EMAIL" ) ) intervals = current_app.config.get("LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS", []) sys.stdout.write( "[!] Creating {num} notifications for {intervals} days as specified by LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS\n".format( num=len(intervals), intervals=",".join([str(x) for x in intervals]) ) ) recipients = current_app.config.get("LEMUR_SECURITY_TEAM_EMAIL") notification_service.create_default_expiration_notifications("DEFAULT_SECURITY", recipients=recipients) sys.stdout.write("[/] Done!\n")
def get(self, certificate_id): """ .. http:get:: /certificates/1/key Retrieves the private key for a given certificate **Example request**: .. sourcecode:: http GET /certificates/1/key HTTP/1.1 Host: example.com Accept: application/json, text/javascript **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "key": "----Begin ...", } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 role = role_service.get_by_name(cert.owner) permission = ViewKeyPermission(certificate_id, getattr(role, 'name', None)) if permission.can(): response = make_response(jsonify(key=cert.private_key), 200) response.headers['cache-control'] = 'private, max-age=0, no-cache, no-store' response.headers['pragma'] = 'no-cache' return response return dict(message='You are not authorized to view this key'), 403
def run(self, username, email, active, roles): role_objs = [] for r in roles: role_obj = role_service.get_by_name(r) if role_obj: role_objs.append(role_obj) else: sys.stderr.write("[!] Cannot find role {0}\n".format(r)) sys.exit(1) password1 = prompt_pass("Password") password2 = prompt_pass("Confirm Password") if password1 != password2: sys.stderr.write("[!] Passwords do not match!\n") sys.exit(1) user_service.create(username, password1, email, active, None, role_objs) sys.stdout.write("[+] Created new user: {0}\n".format(username))
def run(self, username, email, active, roles): role_objs = [] for r in roles: role_obj = role_service.get_by_name(r) if role_obj: role_objs.append(role_obj) else: sys.stderr.write("[!] Cannot find role {0}".format(r)) sys.exit(1) password1 = prompt_pass("Password") password2 = prompt_pass("Confirm Password") if password1 != password2: sys.stderr.write("[!] Passwords do not match") sys.exit(1) user_service.create(username, password1, email, active, None, role_objs) sys.stdout.write("[+] Created new user: {0}".format(username))
def post(self, certificate_id, data=None): """ .. http:post:: /certificates/1/export Export a certificate **Example request**: .. sourcecode:: http PUT /certificates/1/export HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "export": { "plugin": { "pluginOptions": [{ "available": ["Java Key Store (JKS)"], "required": true, "type": "select", "name": "type", "helpMessage": "Choose the format you wish to export", "value": "Java Key Store (JKS)" }, { "required": false, "type": "str", "name": "passphrase", "validation": "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,}$", "helpMessage": "If no passphrase is given one will be generated for you, we highly recommend this. Minimum length is 8." }, { "required": false, "type": "str", "name": "alias", "helpMessage": "Enter the alias you wish to use for the keystore." }], "version": "unknown", "description": "Attempts to generate a JKS keystore or truststore", "title": "Java", "author": "Kevin Glisson", "type": "export", "slug": "java-export" } } } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "data": "base64encodedstring", "passphrase": "UAWOHW#&@_%!tnwmxh832025", "extension": "jks" } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 plugin = data['plugin']['plugin_object'] if plugin.requires_key: if not cert.private_key: return dict( message='Unable to export certificate, plugin: {0} requires a private key but no key was found.'.format( plugin.slug)), 400 else: # allow creators if g.current_user != cert.user: owner_role = role_service.get_by_name(cert.owner) permission = CertificatePermission(owner_role, [x.name for x in cert.roles]) if not permission.can(): return dict(message='You are not authorized to export this certificate.'), 403 options = data['plugin']['plugin_options'] log_service.create(g.current_user, 'key_view', certificate=cert) extension, passphrase, data = plugin.export(cert.body, cert.chain, cert.private_key, options) # we take a hit in message size when b64 encoding return dict(extension=extension, passphrase=passphrase, data=base64.b64encode(data).decode('utf-8'))
def post(self): self.reqparse.add_argument('clientId', type=str, required=True, location='json') self.reqparse.add_argument('redirectUri', type=str, required=True, location='json') self.reqparse.add_argument('code', type=str, required=True, location='json') args = self.reqparse.parse_args() # take the information we have received from the provider to create a new request params = { 'client_id': args['clientId'], 'grant_type': 'authorization_code', 'scope': 'openid email profile address', 'redirect_uri': args['redirectUri'], 'code': args['code'] } # you can either discover these dynamically or simply configure them access_token_url = current_app.config.get('PING_ACCESS_TOKEN_URL') user_api_url = current_app.config.get('PING_USER_API_URL') # the secret and cliendId will be given to you when you signup for the provider basic = base64.b64encode('{0}:{1}'.format( args['clientId'], current_app.config.get("PING_SECRET"))) headers = {'Authorization': 'Basic {0}'.format(basic)} # exchange authorization code for access token. r = requests.post(access_token_url, headers=headers, params=params) id_token = r.json()['id_token'] access_token = r.json()['access_token'] # fetch token public key header_data = fetch_token_header(id_token) jwks_url = current_app.config.get('PING_JWKS_URL') # retrieve the key material as specified by the token header r = requests.get(jwks_url) for key in r.json()['keys']: if key['kid'] == header_data['kid']: secret = get_rsa_public_key(key['n'], key['e']) algo = header_data['alg'] break else: return dict(message='Key not found'), 403 # validate your token based on the key it was signed with try: jwt.decode(id_token, secret, algorithms=[algo], audience=args['clientId']) except jwt.DecodeError: return dict(message='Token is invalid'), 403 except jwt.ExpiredSignatureError: return dict(message='Token has expired'), 403 except jwt.InvalidTokenError: return dict(message='Token is invalid'), 403 user_params = dict(access_token=access_token, schema='profile') # retrieve information about the current user. r = requests.get(user_api_url, params=user_params) profile = r.json() user = user_service.get_by_email(profile['email']) # update their google 'roles' roles = [] for group in profile['googleGroups']: role = role_service.get_by_name(group) if not role: role = role_service.create( group, description= 'This is a google group based role created by Lemur') roles.append(role) # if we get an sso user create them an account # we still pick a random password in case sso is down if not user: # every user is an operator (tied to a default role) if current_app.config.get('LEMUR_DEFAULT_ROLE'): v = role_service.get_by_name( current_app.config.get('LEMUR_DEFAULT_ROLE')) if v: roles.append(v) user = user_service.create(profile['email'], get_psuedo_random_string(), profile['email'], True, profile.get('thumbnailPhotoUrl'), roles) else: # we add 'lemur' specific roles, so they do not get marked as removed for ur in user.roles: if ur.authority_id: roles.append(ur) # update any changes to the user user_service.update( user.id, profile['email'], profile['email'], True, profile.get('thumbnailPhotoUrl' ), # incase profile isn't google+ enabled roles) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) return dict(token=create_token(user))
def put(self, authority_id): """ .. http:put:: /authorities/1 Update a authority **Example request**: .. sourcecode:: http PUT /authorities/1 HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "roles": [], "active": false, "owner": "*****@*****.**", "description": "this is authority1" } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "id": 1, "name": "authority1", "description": "this is authority1", "pluginName": null, "chain": "-----begin ...", "body": "-----begin ...", "active": false, "notBefore": "2015-06-05t17:09:39", "notAfter": "2015-06-10t17:09:39" "options": null } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ self.reqparse.add_argument('roles', type=list, default=[], location='json') self.reqparse.add_argument('active', type=str, location='json', required=True) self.reqparse.add_argument('owner', type=str, location='json', required=True) self.reqparse.add_argument('description', type=str, location='json', required=True) args = self.reqparse.parse_args() authority = service.get(authority_id) role = role_service.get_by_name(authority.owner) # all the authority role members should be allowed roles = [x.name for x in authority.roles] # allow "owner" roles by team DL roles.append(role) permission = AuthorityPermission(authority_id, roles) # we want to make sure that we cannot add roles that we are not members of if not g.current_user.is_admin: role_ids = set([r['id'] for r in args['roles']]) user_role_ids = set([r.id for r in g.current_user.roles]) if not role_ids.issubset(user_role_ids): return dict( message= "You are not allowed to associate a role which you are not a member of" ), 400 if permission.can(): return service.update(authority_id, owner=args['owner'], description=args['description'], active=args['active'], roles=args['roles']) return dict( message="You are not authorized to update this authority"), 403
def put(self, pending_certificate_id, data=None): """ .. http:put:: /pending_certificates/1 Update a pending certificate **Example request**: .. sourcecode:: http PUT /pending certificates/1 HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "owner": "*****@*****.**", "active": false "notifications": [], "destinations": [], "replacements": [] } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "status": null, "cn": "*.test.example.net", "chain": "", "authority": { "active": true, "owner": "*****@*****.**", "id": 1, "description": "verisign test authority", "name": "verisign" }, "owner": "*****@*****.**", "serial": "82311058732025924142789179368889309156", "id": 2288, "issuer": "SymantecCorporation", "destinations": [], "description": null, "deleted": null, "notifications": [{ "id": 1 }] "user": { "username": "******", "active": true, "email": "*****@*****.**", "id": 2 }, "active": true, "number_attempts": 1, "csr": "-----BEGIN CERTIFICATE REQUEST-----...", "external_id": 12345, "domains": [{ "sensitive": false, "id": 1090, "name": "*.test.example.net" }], "replaces": [], "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112", "roles": [{ "id": 464, "description": "This is a google group based role created by Lemur", "name": "*****@*****.**" }], "rotation": true, "rotationPolicy": {"name": "default"}, } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ pending_cert = service.get(pending_certificate_id) if not pending_cert: return dict(message="Cannot find specified pending certificate"), 404 # allow creators if g.current_user != pending_cert.user: owner_role = role_service.get_by_name(pending_cert.owner) permission = CertificatePermission(owner_role, [x.name for x in pending_cert.roles]) if not permission.can(): return dict(message='You are not authorized to update this certificate'), 403 for destination in data['destinations']: if destination.plugin.requires_key: if not pending_cert.private_key: return dict( message='Unable to add destination: {0}. Certificate does not have required private key.'.format( destination.label ) ), 400 pending_cert = service.update(pending_certificate_id, **data) return pending_cert
def post(self, certificate_id): """ .. http:post:: /certificates/1/export Export a certificate **Example request**: .. sourcecode:: http PUT /certificates/1/export HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "export": { "plugin": { "pluginOptions": [{ "available": ["Java Key Store (JKS)"], "required": true, "type": "select", "name": "type", "helpMessage": "Choose the format you wish to export", "value": "Java Key Store (JKS)" }, { "required": false, "type": "str", "name": "passphrase", "validation": "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,}$", "helpMessage": "If no passphrase is given one will be generated for you, we highly recommend this. Minimum length is 8." }, { "required": false, "type": "str", "name": "alias", "helpMessage": "Enter the alias you wish to use for the keystore." }], "version": "unknown", "description": "Attempts to generate a JKS keystore or truststore", "title": "Java", "author": "Kevin Glisson", "type": "export", "slug": "java-export" } } } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "data": "base64encodedstring", "passphrase": "UAWOHW#&@_%!tnwmxh832025", "extension": "jks" } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ self.reqparse.add_argument('export', type=dict, required=True, location='json') args = self.reqparse.parse_args() cert = service.get(certificate_id) role = role_service.get_by_name(cert.owner) permission = UpdateCertificatePermission(certificate_id, getattr(role, 'name', None)) if permission.can(): extension, passphrase, data = service.export(cert, args['export']['plugin']) # we take a hit in message size when b64 encoding return dict(extension=extension, passphrase=passphrase, data=base64.b64encode(data)) return dict(message='You are not authorized to export this certificate'), 403
def put(self, pending_certificate_id, data=None): """ .. http:put:: /pending_certificates/1 Update a pending certificate **Example request**: .. sourcecode:: http PUT /pending certificates/1 HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "owner": "*****@*****.**", "active": false "notifications": [], "destinations": [], "replacements": [] } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "status": null, "cn": "*.test.example.net", "chain": "", "authority": { "active": true, "owner": "*****@*****.**", "id": 1, "description": "verisign test authority", "name": "verisign" }, "owner": "*****@*****.**", "serial": "82311058732025924142789179368889309156", "id": 2288, "issuer": "SymantecCorporation", "destinations": [], "description": null, "deleted": null, "notifications": [{ "id": 1 }] "user": { "username": "******", "active": true, "email": "*****@*****.**", "id": 2 }, "active": true, "number_attempts": 1, "csr": "-----BEGIN CERTIFICATE REQUEST-----...", "external_id": 12345, "domains": [{ "sensitive": false, "id": 1090, "name": "*.test.example.net" }], "replaces": [], "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112", "roles": [{ "id": 464, "description": "This is a google group based role created by Lemur", "name": "*****@*****.**" }], "rotation": true, "rotationPolicy": {"name": "default"}, } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ pending_cert = service.get(pending_certificate_id) if not pending_cert: return dict(message="Cannot find specified pending certificate"), 404 # allow creators if g.current_user != pending_cert.user: owner_role = role_service.get_by_name(pending_cert.owner) permission = CertificatePermission( owner_role, [x.name for x in pending_cert.roles] ) if not permission.can(): return ( dict(message="You are not authorized to update this certificate"), 403, ) for destination in data["destinations"]: if destination.plugin.requires_key: if not pending_cert.private_key: return ( dict( message="Unable to add destination: {0}. Certificate does not have required private key.".format( destination.label ) ), 400, ) pending_cert = service.update(pending_certificate_id, **data) return pending_cert
def post(self, data=None): """ .. http:post:: /certificates Creates a new certificate **Example request**: .. sourcecode:: http POST /certificates HTTP/1.1 Host: example.com Accept: application/json, text/javascript **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "status": null, "cn": "*.test.example.net", "chain": "", "authority": { "active": true, "owner": "*****@*****.**", "id": 1, "description": "verisign test authority", "name": "verisign" }, "owner": "*****@*****.**", "serial": "82311058732025924142789179368889309156", "id": 2288, "issuer": "SymantecCorporation", "notBefore": "2016-06-03T00:00:00+00:00", "notAfter": "2018-01-12T23:59:59+00:00", "destinations": [], "bits": 2048, "body": "-----BEGIN CERTIFICATE-----...", "description": null, "deleted": null, "notifications": [{ "id": 1 }] "signingAlgorithm": "sha256", "user": { "username": "******", "active": true, "email": "*****@*****.**", "id": 2 }, "active": true, "domains": [{ "sensitive": false, "id": 1090, "name": "*.test.example.net" }], "replaces": [], "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112", "roles": [{ "id": 464, "description": "This is a google group based role created by Lemur", "name": "*****@*****.**" }], "san": null } :arg extensions: extensions to be used in the certificate :arg description: description for new certificate :arg owner: owner email :arg validityStart: when the certificate should start being valid :arg validityEnd: when the certificate should expire :arg authority: authority that should issue the certificate :arg country: country for the CSR :arg state: state for the CSR :arg location: location for the CSR :arg organization: organization for CSR :arg commonName: certificate common name :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ role = role_service.get_by_name(data['authority'].owner) # all the authority role members should be allowed roles = [x.name for x in data['authority'].roles] # allow "owner" roles by team DL roles.append(role) authority_permission = AuthorityPermission(data['authority'].id, roles) if authority_permission.can(): return service.create(**data) return dict(message="You are not authorized to use {0}".format(data['authority'].name)), 403
def put(self, certificate_id): """ .. http:put:: /certificates/1 Update a certificate **Example request**: .. sourcecode:: http PUT /certificates/1 HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "owner": "*****@*****.**", "active": false "notifications": [], "destinations": [], "replacements": [] } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "id": 1, "name": "cert1", "description": "this is cert1", "bits": 2048, "deleted": false, "issuer": "ExampeInc.", "serial": "123450", "chain": "-----Begin ...", "body": "-----Begin ...", "san": true, "owner": "*****@*****.**", "active": false, "notBefore": "2015-06-05T17:09:39", "notAfter": "2015-06-10T17:09:39", "cn": "example.com", "status": "unknown", } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ self.reqparse.add_argument('active', type=bool, location='json') self.reqparse.add_argument('owner', type=str, location='json') self.reqparse.add_argument('description', type=str, location='json') self.reqparse.add_argument('destinations', type=list, default=[], location='json') self.reqparse.add_argument('notifications', type=notification_list, default=[], location='json') self.reqparse.add_argument('replacements', type=list, default=[], location='json') args = self.reqparse.parse_args() cert = service.get(certificate_id) role = role_service.get_by_name(cert.owner) permission = UpdateCertificatePermission(certificate_id, getattr(role, 'name', None)) if permission.can(): return service.update(certificate_id, args['owner'], args['description'], args['active'], args['destinations'], args['notifications'], args['replacements']) return dict( message='You are not authorized to update this certificate'), 403
def post(self, data=None): """ .. http:post:: /certificates Creates a new certificate **Example request**: .. sourcecode:: http POST /certificates HTTP/1.1 Host: example.com Accept: application/json, text/javascript **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "status": null, "cn": "*.test.example.net", "chain": "", "authority": { "active": true, "owner": "*****@*****.**", "id": 1, "description": "verisign test authority", "name": "verisign" }, "owner": "*****@*****.**", "serial": "82311058732025924142789179368889309156", "id": 2288, "issuer": "SymantecCorporation", "notBefore": "2016-06-03T00:00:00+00:00", "notAfter": "2018-01-12T23:59:59+00:00", "destinations": [], "bits": 2048, "body": "-----BEGIN CERTIFICATE-----...", "description": null, "deleted": null, "notifications": [{ "id": 1 }] "signingAlgorithm": "sha256", "user": { "username": "******", "active": true, "email": "*****@*****.**", "id": 2 }, "active": true, "domains": [{ "sensitive": false, "id": 1090, "name": "*.test.example.net" }], "replaces": [], "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112", "roles": [{ "id": 464, "description": "This is a google group based role created by Lemur", "name": "*****@*****.**" }], "san": null } :arg extensions: extensions to be used in the certificate :arg description: description for new certificate :arg owner: owner email :arg validityStart: when the certificate should start being valid :arg validityEnd: when the certificate should expire :arg authority: authority that should issue the certificate :arg country: country for the CSR :arg state: state for the CSR :arg location: location for the CSR :arg organization: organization for CSR :arg commonName: certificate common name :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ role = role_service.get_by_name(data['authority'].owner) # all the authority role members should be allowed roles = [x.name for x in data['authority'].roles] # allow "owner" roles by team DL roles.append(role) authority_permission = AuthorityPermission(data['authority'].id, roles) if authority_permission.can(): return service.create(**data) return dict(message="You are not authorized to use {0}".format( data['authority'].name)), 403
def post(self, certificate_id): """ .. http:post:: /certificates/1/export Export a certificate **Example request**: .. sourcecode:: http PUT /certificates/1/export HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "export": { "plugin": { "pluginOptions": [{ "available": ["Java Key Store (JKS)"], "required": true, "type": "select", "name": "type", "helpMessage": "Choose the format you wish to export", "value": "Java Key Store (JKS)" }, { "required": false, "type": "str", "name": "passphrase", "validation": "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,}$", "helpMessage": "If no passphrase is given one will be generated for you, we highly recommend this. Minimum length is 8." }, { "required": false, "type": "str", "name": "alias", "helpMessage": "Enter the alias you wish to use for the keystore." }], "version": "unknown", "description": "Attempts to generate a JKS keystore or truststore", "title": "Java", "author": "Kevin Glisson", "type": "export", "slug": "java-export" } } } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "data": "base64encodedstring", "passphrase": "UAWOHW#&@_%!tnwmxh832025", "extension": "jks" } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ self.reqparse.add_argument('export', type=dict, required=True, location='json') args = self.reqparse.parse_args() cert = service.get(certificate_id) role = role_service.get_by_name(cert.owner) permission = UpdateCertificatePermission(certificate_id, getattr(role, 'name', None)) plugin = plugins.get(args['export']['plugin']['slug']) if plugin.requires_key: if permission.can(): extension, passphrase, data = plugin.export( cert.body, cert.chain, cert.private_key, args['export']['plugin']['pluginOptions']) else: return dict( message='You are not authorized to export this certificate' ), 403 else: extension, passphrase, data = plugin.export( cert.body, cert.chain, cert.private_key, args['export']['plugin']['pluginOptions']) # we take a hit in message size when b64 encoding return dict(extension=extension, passphrase=passphrase, data=base64.b64encode(data))
def post(self): self.reqparse.add_argument('clientId', type=str, required=True, location='json') self.reqparse.add_argument('redirectUri', type=str, required=True, location='json') self.reqparse.add_argument('code', type=str, required=True, location='json') args = self.reqparse.parse_args() # take the information we have received from the provider to create a new request params = { 'grant_type': 'authorization_code', 'scope': 'openid email profile groups', 'redirect_uri': args['redirectUri'], 'code': args['code'], } # you can either discover these dynamically or simply configure them access_token_url = current_app.config.get('OAUTH2_ACCESS_TOKEN_URL') user_api_url = current_app.config.get('OAUTH2_USER_API_URL') verify_cert = current_app.config.get('OAUTH2_VERIFY_CERT', True) # the secret and cliendId will be given to you when you signup for the provider token = '{0}:{1}'.format(args['clientId'], current_app.config.get("OAUTH2_SECRET")) basic = base64.b64encode(bytes(token, 'utf-8')) headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'authorization': 'basic {0}'.format(basic.decode('utf-8')) } # exchange authorization code for access token. # Try Params first r = requests.post(access_token_url, headers=headers, params=params, verify=verify_cert) if r.status_code == 400: r = requests.post(access_token_url, headers=headers, data=params, verify=verify_cert) id_token = r.json()['id_token'] access_token = r.json()['access_token'] # fetch token public key header_data = fetch_token_header(id_token) jwks_url = current_app.config.get('OAUTH2_JWKS_URL') # retrieve the key material as specified by the token header r = requests.get(jwks_url, verify=verify_cert) for key in r.json()['keys']: if key['kid'] == header_data['kid']: secret = get_rsa_public_key(key['n'], key['e']) algo = header_data['alg'] break else: return dict(message='Key not found'), 401 # validate your token based on the key it was signed with try: if sys.version_info >= (3, 0): jwt.decode(id_token, secret.decode('utf-8'), algorithms=[algo], audience=args['clientId']) else: jwt.decode(id_token, secret, algorithms=[algo], audience=args['clientId']) except jwt.DecodeError: return dict(message='Token is invalid'), 401 except jwt.ExpiredSignatureError: return dict(message='Token has expired'), 401 except jwt.InvalidTokenError: return dict(message='Token is invalid'), 401 headers = {'authorization': 'Bearer {0}'.format(access_token)} # retrieve information about the current user. r = requests.get(user_api_url, headers=headers, verify=verify_cert) profile = r.json() user = user_service.get_by_email(profile['email']) metrics.send('successful_login', 'counter', 1) # update with roles sent by identity provider roles = [] if 'roles' in profile: for group in profile['roles']: role = role_service.get_by_name(group) if not role: role = role_service.create( group, description= 'This is a group configured by identity provider', third_party=True) if not role.third_party: role = role_service.set_third_party( role.id, third_party_status=True) roles.append(role) role = role_service.get_by_name(profile['email']) if not role: role = role_service.create( profile['email'], description='This is a user specific role', third_party=True) if not role.third_party: role = role_service.set_third_party(role.id, third_party_status=True) roles.append(role) # if we get an sso user create them an account if not user: # every user is an operator (tied to a default role) if current_app.config.get('LEMUR_DEFAULT_ROLE'): v = role_service.get_by_name( current_app.config.get('LEMUR_DEFAULT_ROLE')) if not v.third_party: v = role_service.set_third_party(v.id, third_party_status=True) if v: roles.append(v) user = user_service.create(profile['name'], get_psuedo_random_string(), profile['email'], True, profile.get('thumbnailPhotoUrl'), roles) else: # we add 'lemur' specific roles, so they do not get marked as removed for ur in user.roles: if not ur.third_party: roles.append(ur) # update any changes to the user user_service.update( user.id, profile['name'], profile['email'], True, profile.get('thumbnailPhotoUrl' ), # incase profile isn't google+ enabled roles) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) return dict(token=create_token(user))
def run(self, password): create() user = user_service.get_by_username("lemur") admin_role = role_service.get_by_name('admin') if admin_role: sys.stdout.write("[-] Admin role already created, skipping...!\n") else: # we create an admin role admin_role = role_service.create('admin', description='This is the Lemur administrator role.') sys.stdout.write("[+] Created 'admin' role\n") operator_role = role_service.get_by_name('operator') if operator_role: sys.stdout.write("[-] Operator role already created, skipping...!\n") else: # we create an operator role operator_role = role_service.create('operator', description='This is the Lemur operator role.') sys.stdout.write("[+] Created 'operator' role\n") read_only_role = role_service.get_by_name('read-only') if read_only_role: sys.stdout.write("[-] Read only role already created, skipping...!\n") else: # we create an read only role read_only_role = role_service.create('read-only', description='This is the Lemur read only role.') sys.stdout.write("[+] Created 'read-only' role\n") if not user: if not password: sys.stdout.write("We need to set Lemur's password to continue!\n") password = prompt_pass("Password") password1 = prompt_pass("Confirm Password") if password != password1: sys.stderr.write("[!] Passwords do not match!\n") sys.exit(1) user_service.create("lemur", password, '*****@*****.**', True, None, [admin_role]) sys.stdout.write("[+] Created the user 'lemur' and granted it the 'admin' role!\n") else: sys.stdout.write("[-] Default user has already been created, skipping...!\n") intervals = current_app.config.get("LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS", []) sys.stdout.write( "[!] Creating {num} notifications for {intervals} days as specified by LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS\n".format( num=len(intervals), intervals=",".join([str(x) for x in intervals]) ) ) recipients = current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL') sys.stdout.write("[+] Creating expiration email notifications!\n") sys.stdout.write("[!] Using {0} as specified by LEMUR_SECURITY_TEAM_EMAIL for notifications\n".format(recipients)) notification_service.create_default_expiration_notifications("DEFAULT_SECURITY", recipients=recipients) _DEFAULT_ROTATION_INTERVAL = 'default' default_rotation_interval = policy_service.get_by_name(_DEFAULT_ROTATION_INTERVAL) if default_rotation_interval: sys.stdout.write("[-] Default rotation interval policy already created, skipping...!\n") else: days = current_app.config.get("LEMUR_DEFAULT_ROTATION_INTERVAL", 30) sys.stdout.write("[+] Creating default certificate rotation policy of {days} days before issuance.\n".format( days=days)) policy_service.create(days=days, name=_DEFAULT_ROTATION_INTERVAL) sys.stdout.write("[/] Done!\n")
def post(self): """ .. http:post:: /certificates Creates a new certificate **Example request**: .. sourcecode:: http POST /certificates HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "country": "US", "state": "CA", "location": "A Place", "organization": "ExampleInc.", "organizationalUnit": "Operations", "owner": "*****@*****.**", "description": "test", "selectedAuthority": "timetest2", "csr": "----BEGIN CERTIFICATE REQUEST-----...", "authority": { "body": "-----BEGIN...", "name": "timetest2", "chain": "", "notBefore": "2015-06-05T15:20:59", "active": true, "id": 50, "notAfter": "2015-06-17T15:21:08", "description": "dsfdsf" }, "notifications": [ { "description": "Default 30 day expiration notification", "notificationOptions": [ { "name": "interval", "required": true, "value": 30, "helpMessage": "Number of days to be alert before expiration.", "validation": "^\\d+$", "type": "int" }, { "available": [ "days", "weeks", "months" ], "name": "unit", "required": true, "value": "days", "helpMessage": "Interval unit", "validation": "", "type": "select" }, { "name": "recipients", "required": true, "value": "*****@*****.**", "helpMessage": "Comma delimited list of email addresses", "validation": "^([\\w+-.%]+@[\\w-.]+\\.[A-Za-z]{2,4},?)+$", "type": "str" } ], "label": "DEFAULT_KGLISSON_30_DAY", "pluginName": "email-notification", "active": true, "id": 7 } ], "extensions": { "basicConstraints": {}, "keyUsage": { "isCritical": true, "useKeyEncipherment": true, "useDigitalSignature": true }, "extendedKeyUsage": { "isCritical": true, "useServerAuthentication": true }, "subjectKeyIdentifier": { "includeSKI": true }, "subAltNames": { "names": [] } }, "commonName": "test", "validityStart": "2015-06-05T07:00:00.000Z", "validityEnd": "2015-06-16T07:00:00.000Z", "replacements": [ {'id': 123} ] } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "id": 1, "name": "cert1", "description": "this is cert1", "bits": 2048, "deleted": false, "issuer": "ExampeInc.", "serial": "123450", "chain": "-----Begin ...", "body": "-----Begin ...", "san": true, "owner": "*****@*****.**", "active": false, "notBefore": "2015-06-05T17:09:39", "notAfter": "2015-06-10T17:09:39", "cn": "example.com", "status": "unknown" } :arg extensions: extensions to be used in the certificate :arg description: description for new certificate :arg owner: owner email :arg validityStart: when the certificate should start being valid :arg validityEnd: when the certificate should expire :arg authority: authority that should issue the certificate :arg country: country for the CSR :arg state: state for the CSR :arg location: location for the CSR :arg organization: organization for CSR :arg commonName: certiifcate common name :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ self.reqparse.add_argument('extensions', type=dict, location='json') self.reqparse.add_argument('destinations', type=list, default=[], location='json') self.reqparse.add_argument('notifications', type=list, default=[], location='json') self.reqparse.add_argument('replacements', type=list, default=[], location='json') self.reqparse.add_argument('validityStart', type=str, location='json') # TODO validate self.reqparse.add_argument('validityEnd', type=str, location='json') # TODO validate self.reqparse.add_argument('validityYears', type=int, location='json') # TODO validate self.reqparse.add_argument('authority', type=valid_authority, location='json', required=True) self.reqparse.add_argument('description', type=str, location='json') self.reqparse.add_argument('country', type=str, location='json', required=True) self.reqparse.add_argument('state', type=str, location='json', required=True) self.reqparse.add_argument('location', type=str, location='json', required=True) self.reqparse.add_argument('organization', type=str, location='json', required=True) self.reqparse.add_argument('organizationalUnit', type=str, location='json', required=True) self.reqparse.add_argument('owner', type=str, location='json', required=True) self.reqparse.add_argument('commonName', type=str, location='json', required=True) self.reqparse.add_argument('csr', type=str, location='json') args = self.reqparse.parse_args() authority = args['authority'] role = role_service.get_by_name(authority.owner) # all the authority role members should be allowed roles = [x.name for x in authority.roles] # allow "owner" roles by team DL roles.append(role) authority_permission = AuthorityPermission(authority.id, roles) if authority_permission.can(): # if we are not admins lets make sure we aren't issuing anything sensitive if not SensitiveDomainPermission().can(): check_sensitive_domains(get_domains_from_options(args)) return service.create(**args) return dict(message="You are not authorized to use {0}".format( args['authority'].name)), 403
def post(self, certificate_id, data=None): """ .. http:post:: /certificates/1/export Export a certificate **Example request**: .. sourcecode:: http PUT /certificates/1/export HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "export": { "plugin": { "pluginOptions": [{ "available": ["Java Key Store (JKS)"], "required": true, "type": "select", "name": "type", "helpMessage": "Choose the format you wish to export", "value": "Java Key Store (JKS)" }, { "required": false, "type": "str", "name": "passphrase", "validation": "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,}$", "helpMessage": "If no passphrase is given one will be generated for you, we highly recommend this. Minimum length is 8." }, { "required": false, "type": "str", "name": "alias", "helpMessage": "Enter the alias you wish to use for the keystore." }], "version": "unknown", "description": "Attempts to generate a JKS keystore or truststore", "title": "Java", "author": "Kevin Glisson", "type": "export", "slug": "java-export" } } } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "data": "base64encodedstring", "passphrase": "UAWOHW#&@_%!tnwmxh832025", "extension": "jks" } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 plugin = data['plugin']['plugin_object'] if plugin.requires_key: if not cert.private_key: return dict( message= 'Unable to export certificate, plugin: {0} requires a private key but no key was found.' .format(plugin.slug)), 400 else: # allow creators if g.current_user != cert.user: owner_role = role_service.get_by_name(cert.owner) permission = CertificatePermission( owner_role, [x.name for x in cert.roles]) if not permission.can(): return dict( message= 'You are not authorized to export this certificate.' ), 403 options = data['plugin']['plugin_options'] log_service.create(g.current_user, 'key_view', certificate=cert) extension, passphrase, data = plugin.export(cert.body, cert.chain, cert.private_key, options) # we take a hit in message size when b64 encoding return dict(extension=extension, passphrase=passphrase, data=base64.b64encode(data).decode('utf-8'))
def put(self, certificate_id, data=None): """ .. http:put:: /certificates/1 Update a certificate **Example request**: .. sourcecode:: http PUT /certificates/1 HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "owner": "*****@*****.**", "active": false "notifications": [], "destinations": [], "replacements": [] } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "status": null, "cn": "*.test.example.net", "chain": "", "authority": { "active": true, "owner": "*****@*****.**", "id": 1, "description": "verisign test authority", "name": "verisign" }, "owner": "*****@*****.**", "serial": "82311058732025924142789179368889309156", "id": 2288, "issuer": "SymantecCorporation", "notBefore": "2016-06-03T00:00:00+00:00", "notAfter": "2018-01-12T23:59:59+00:00", "destinations": [], "bits": 2048, "body": "-----BEGIN CERTIFICATE-----...", "description": null, "deleted": null, "notifications": [{ "id": 1 }] "signingAlgorithm": "sha256", "user": { "username": "******", "active": true, "email": "*****@*****.**", "id": 2 }, "active": true, "domains": [{ "sensitive": false, "id": 1090, "name": "*.test.example.net" }], "replaces": [], "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112", "roles": [{ "id": 464, "description": "This is a google group based role created by Lemur", "name": "*****@*****.**" }], "san": null } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ cert = service.get(certificate_id) owner_role = role_service.get_by_name(cert.owner) permission = CertificatePermission(cert.id, owner_role, [x.name for x in cert.roles]) if permission.can(): for destination in data['destinations']: if destination.plugin.requires_key: if not cert.private_key: return dict('Unable to add destination: {0}. Certificate does not have required private key.'.format(destination.label)) return service.update( certificate_id, data['owner'], data['description'], data['active'], data['destinations'], data['notifications'], data['replacements'], data['roles'] ) return dict(message='You are not authorized to update this certificate'), 403
def post(self, data=None): """ .. http:post:: /certificates Creates a new certificate **Example request**: .. sourcecode:: http POST /certificates HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "owner": "*****@*****.**", "commonName": "test.example.net", "country": "US", "extensions": { "subAltNames": { "names": [ { "nameType": "DNSName", "value": "*.test.example.net" }, { "nameType": "DNSName", "value": "www.test.example.net" } ] } }, "replacements": [{ "id": 1 }], "notify": true, "validityEnd": "2026-01-01T08:00:00.000Z", "authority": { "name": "verisign" }, "organization": "Netflix, Inc.", "location": "Los Gatos", "state": "California", "validityStart": "2016-11-11T04:19:48.000Z", "organizationalUnit": "Operations" } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "status": null, "cn": "*.test.example.net", "chain": "", "authority": { "active": true, "owner": "*****@*****.**", "id": 1, "description": "verisign test authority", "name": "verisign" }, "owner": "*****@*****.**", "serial": "82311058732025924142789179368889309156", "id": 2288, "issuer": "SymantecCorporation", "dateCreated": "2016-06-03T06:09:42.133769+00:00", "notBefore": "2016-06-03T00:00:00+00:00", "notAfter": "2018-01-12T23:59:59+00:00", "destinations": [], "bits": 2048, "body": "-----BEGIN CERTIFICATE-----...", "description": null, "deleted": null, "notifications": [{ "id": 1 }], "signingAlgorithm": "sha256", "user": { "username": "******", "active": true, "email": "*****@*****.**", "id": 2 }, "active": true, "domains": [{ "sensitive": false, "id": 1090, "name": "*.test.example.net" }], "replaces": [{ "id": 1 }], "rotation": true, "rotationPolicy": {"name": "default"}, "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112", "roles": [{ "id": 464, "description": "This is a google group based role created by Lemur", "name": "*****@*****.**" }], "san": null } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ role = role_service.get_by_name(data['authority'].owner) # all the authority role members should be allowed roles = [x.name for x in data['authority'].roles] # allow "owner" roles by team DL roles.append(role) authority_permission = AuthorityPermission(data['authority'].id, roles) if authority_permission.can(): data['creator'] = g.user cert = service.create(**data) if isinstance(cert, Certificate): # only log if created, not pending log_service.create(g.user, 'create_cert', certificate=cert) return cert return dict(message="You are not authorized to use the authority: {0}".format(data['authority'].name)), 403
def post(self): self.reqparse.add_argument("clientId", type=str, required=True, location="json") self.reqparse.add_argument("redirectUri", type=str, required=True, location="json") self.reqparse.add_argument("code", type=str, required=True, location="json") args = self.reqparse.parse_args() # take the information we have received from the provider to create a new request params = { "client_id": args["clientId"], "grant_type": "authorization_code", "scope": "openid email profile address", "redirect_uri": args["redirectUri"], "code": args["code"], } # you can either discover these dynamically or simply configure them access_token_url = current_app.config.get("PING_ACCESS_TOKEN_URL") user_api_url = current_app.config.get("PING_USER_API_URL") # the secret and cliendId will be given to you when you signup for the provider token = "{0}:{1}".format(args["clientId"], current_app.config.get("PING_SECRET")) if sys.version_info >= (3, 0): basic = base64.b64encode(bytes(token, "utf-8")) headers = {"authorization": "basic {0}".format(basic.decode("utf-8"))} else: basic = base64.b64encode(token, "utf-8") headers = {"authorization": "basic {0}".format(basic)} # exchange authorization code for access token. r = requests.post(access_token_url, headers=headers, params=params) id_token = r.json()["id_token"] access_token = r.json()["access_token"] # fetch token public key header_data = fetch_token_header(id_token) jwks_url = current_app.config.get("PING_JWKS_URL") # retrieve the key material as specified by the token header r = requests.get(jwks_url) for key in r.json()["keys"]: if key["kid"] == header_data["kid"]: secret = get_rsa_public_key(key["n"], key["e"]) algo = header_data["alg"] break else: return dict(message="Key not found"), 403 # validate your token based on the key it was signed with try: if sys.version_info >= (3, 0): jwt.decode(id_token, secret.decode("utf-8"), algorithms=[algo], audience=args["clientId"]) else: jwt.decode(id_token, secret, algorithms=[algo], audience=args["clientId"]) except jwt.DecodeError: return dict(message="Token is invalid"), 403 except jwt.ExpiredSignatureError: return dict(message="Token has expired"), 403 except jwt.InvalidTokenError: return dict(message="Token is invalid"), 403 user_params = dict(access_token=access_token, schema="profile") # retrieve information about the current user. r = requests.get(user_api_url, params=user_params) profile = r.json() user = user_service.get_by_email(profile["email"]) metrics.send("successful_login", "counter", 1) # update their google 'roles' roles = [] for group in profile["googleGroups"]: role = role_service.get_by_name(group) if not role: role = role_service.create(group, description="This is a google group based role created by Lemur") roles.append(role) role = role_service.get_by_name(profile["email"]) if not role: role = role_service.create(profile["email"], description="This is a user specific role") roles.append(role) # if we get an sso user create them an account if not user: # every user is an operator (tied to a default role) if current_app.config.get("LEMUR_DEFAULT_ROLE"): v = role_service.get_by_name(current_app.config.get("LEMUR_DEFAULT_ROLE")) if v: roles.append(v) user = user_service.create( profile["email"], get_psuedo_random_string(), profile["email"], True, profile.get("thumbnailPhotoUrl"), roles, ) else: # we add 'lemur' specific roles, so they do not get marked as removed for ur in user.roles: if ur.authority_id: roles.append(ur) # update any changes to the user user_service.update( user.id, profile["email"], profile["email"], True, profile.get("thumbnailPhotoUrl"), # incase profile isn't google+ enabled roles, ) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) return dict(token=create_token(user))
def create(kwargs): """ Create a new authority. :return: """ issuer = plugins.get(kwargs.get('pluginName')) kwargs['creator'] = g.current_user.email cert_body, intermediate, issuer_roles = issuer.create_authority(kwargs) cert = Certificate(cert_body, chain=intermediate) cert.owner = kwargs['ownerEmail'] if kwargs['caType'] == 'subca': cert.description = "This is the ROOT certificate for the {0} sub certificate authority the parent \ authority is {1}.".format( kwargs.get('caName'), kwargs.get('caParent')) else: cert.description = "This is the ROOT certificate for the {0} certificate authority.".format( kwargs.get('caName')) cert.user = g.current_user cert.notifications = notification_service.create_default_expiration_notifications( 'DEFAULT_SECURITY', current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL')) # we create and attach any roles that the issuer gives us role_objs = [] for r in issuer_roles: role = role_service.create( r['name'], password=r['password'], description="{0} auto generated role".format( kwargs.get('pluginName')), username=r['username']) # the user creating the authority should be able to administer it if role.username == 'admin': g.current_user.roles.append(role) role_objs.append(role) authority = Authority(kwargs.get('caName'), kwargs['ownerEmail'], kwargs['pluginName'], cert_body, description=kwargs['caDescription'], chain=intermediate, roles=role_objs) database.update(cert) authority = database.create(authority) # the owning dl or role should have this authority associated with it owner_role = role_service.get_by_name(kwargs['ownerEmail']) if not owner_role: owner_role = role_service.create(kwargs['ownerEmail']) owner_role.authority = authority g.current_user.authorities.append(authority) return authority
def post(self, data=None): """ .. http:post:: /certificates Creates a new certificate **Example request**: .. sourcecode:: http POST /certificates HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "owner": "*****@*****.**", "commonName": "test.example.net", "country": "US", "extensions": { "subAltNames": { "names": [ { "nameType": "DNSName", "value": "*.test.example.net" }, { "nameType": "DNSName", "value": "www.test.example.net" } ] } }, "replacements": [{ "id": 1 }, "notify": true, "validityEnd": "2026-01-01T08:00:00.000Z", "authority": { "name": "verisign" }, "organization": "Netflix, Inc.", "location": "Los Gatos", "state": "California", "validityStart": "2016-11-11T04:19:48.000Z", "organizationalUnit": "Operations" } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "status": null, "cn": "*.test.example.net", "chain": "", "authority": { "active": true, "owner": "*****@*****.**", "id": 1, "description": "verisign test authority", "name": "verisign" }, "owner": "*****@*****.**", "serial": "82311058732025924142789179368889309156", "id": 2288, "issuer": "SymantecCorporation", "notBefore": "2016-06-03T00:00:00+00:00", "notAfter": "2018-01-12T23:59:59+00:00", "destinations": [], "bits": 2048, "body": "-----BEGIN CERTIFICATE-----...", "description": null, "deleted": null, "notifications": [{ "id": 1 }] "signingAlgorithm": "sha256", "user": { "username": "******", "active": true, "email": "*****@*****.**", "id": 2 }, "active": true, "domains": [{ "sensitive": false, "id": 1090, "name": "*.test.example.net" }], "replaces": [{ "id": 1 }], "rotation": True, "rotationPolicy": {"name": "default"}, "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112", "roles": [{ "id": 464, "description": "This is a google group based role created by Lemur", "name": "*****@*****.**" }], "san": null } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ role = role_service.get_by_name(data['authority'].owner) # all the authority role members should be allowed roles = [x.name for x in data['authority'].roles] # allow "owner" roles by team DL roles.append(role) authority_permission = AuthorityPermission(data['authority'].id, roles) if authority_permission.can(): data['creator'] = g.user cert = service.create(**data) log_service.create(g.user, 'create_cert', certificate=cert) return cert return dict(message="You are not authorized to use the authority: {0}". format(data['authority'].name)), 403
def post(self): """ .. http:post:: /certificates Creates a new certificate **Example request**: .. sourcecode:: http POST /certificates HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "country": "US", "state": "CA", "location": "A Place", "organization": "ExampleInc.", "organizationalUnit": "Operations", "owner": "*****@*****.**", "description": "test", "selectedAuthority": "timetest2", "csr", "authority": { "body": "-----BEGIN...", "name": "timetest2", "chain": "", "notBefore": "2015-06-05T15:20:59", "active": true, "id": 50, "notAfter": "2015-06-17T15:21:08", "description": "dsfdsf" }, "notifications": [ { "description": "Default 30 day expiration notification", "notificationOptions": [ { "name": "interval", "required": true, "value": 30, "helpMessage": "Number of days to be alert before expiration.", "validation": "^\\d+$", "type": "int" }, { "available": [ "days", "weeks", "months" ], "name": "unit", "required": true, "value": "days", "helpMessage": "Interval unit", "validation": "", "type": "select" }, { "name": "recipients", "required": true, "value": "*****@*****.**", "helpMessage": "Comma delimited list of email addresses", "validation": "^([\\w+-.%]+@[\\w-.]+\\.[A-Za-z]{2,4},?)+$", "type": "str" } ], "label": "DEFAULT_KGLISSON_30_DAY", "pluginName": "email-notification", "active": true, "id": 7 } ], "extensions": { "basicConstraints": {}, "keyUsage": { "isCritical": true, "useKeyEncipherment": true, "useDigitalSignature": true }, "extendedKeyUsage": { "isCritical": true, "useServerAuthentication": true }, "subjectKeyIdentifier": { "includeSKI": true }, "subAltNames": { "names": [] } }, "commonName": "test", "validityStart": "2015-06-05T07:00:00.000Z", "validityEnd": "2015-06-16T07:00:00.000Z", "replacements": [ {'id': 123} ] } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "id": 1, "name": "cert1", "description": "this is cert1", "bits": 2048, "deleted": false, "issuer": "ExampeInc.", "serial": "123450", "chain": "-----Begin ...", "body": "-----Begin ...", "san": true, "owner": "*****@*****.**", "active": false, "notBefore": "2015-06-05T17:09:39", "notAfter": "2015-06-10T17:09:39", "cn": "example.com", "status": "unknown" } :arg extensions: extensions to be used in the certificate :arg description: description for new certificate :arg owner: owner email :arg validityStart: when the certificate should start being valid :arg validityEnd: when the certificate should expire :arg authority: authority that should issue the certificate :arg country: country for the CSR :arg state: state for the CSR :arg location: location for the CSR :arg organization: organization for CSR :arg commonName: certiifcate common name :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ self.reqparse.add_argument('extensions', type=dict, location='json') self.reqparse.add_argument('destinations', type=list, default=[], location='json') self.reqparse.add_argument('notifications', type=list, default=[], location='json') self.reqparse.add_argument('replacements', type=list, default=[], location='json') self.reqparse.add_argument('validityStart', type=str, location='json') # TODO validate self.reqparse.add_argument('validityEnd', type=str, location='json') # TODO validate self.reqparse.add_argument('authority', type=valid_authority, location='json', required=True) self.reqparse.add_argument('description', type=str, location='json') self.reqparse.add_argument('country', type=str, location='json', required=True) self.reqparse.add_argument('state', type=str, location='json', required=True) self.reqparse.add_argument('location', type=str, location='json', required=True) self.reqparse.add_argument('organization', type=str, location='json', required=True) self.reqparse.add_argument('organizationalUnit', type=str, location='json', required=True) self.reqparse.add_argument('owner', type=str, location='json', required=True) self.reqparse.add_argument('commonName', type=str, location='json', required=True) self.reqparse.add_argument('csr', type=str, location='json') args = self.reqparse.parse_args() authority = args['authority'] role = role_service.get_by_name(authority.owner) # all the authority role members should be allowed roles = [x.name for x in authority.roles] # allow "owner" roles by team DL roles.append(role) permission = AuthorityPermission(authority.id, roles) if permission.can(): return service.create(**args) return dict(message="You are not authorized to use {0}".format(args['authority'].name)), 403
def put(self, certificate_id, data=None): """ .. http:put:: /certificates/1 Update a certificate **Example request**: .. sourcecode:: http PUT /certificates/1 HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "owner": "*****@*****.**", "active": false "notifications": [], "destinations": [], "replacements": [] } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "status": null, "cn": "*.test.example.net", "chain": "", "authority": { "active": true, "owner": "*****@*****.**", "id": 1, "description": "verisign test authority", "name": "verisign" }, "owner": "*****@*****.**", "serial": "82311058732025924142789179368889309156", "id": 2288, "issuer": "SymantecCorporation", "notBefore": "2016-06-03T00:00:00+00:00", "notAfter": "2018-01-12T23:59:59+00:00", "destinations": [], "bits": 2048, "body": "-----BEGIN CERTIFICATE-----...", "description": null, "deleted": null, "notifications": [{ "id": 1 }] "signingAlgorithm": "sha256", "user": { "username": "******", "active": true, "email": "*****@*****.**", "id": 2 }, "active": true, "domains": [{ "sensitive": false, "id": 1090, "name": "*.test.example.net" }], "replaces": [], "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112", "roles": [{ "id": 464, "description": "This is a google group based role created by Lemur", "name": "*****@*****.**" }], "rotation": True, "rotationPolicy": {"name": "default"}, "san": null } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ cert = service.get(certificate_id) if not cert: return dict(message="Cannot find specified certificate"), 404 # allow creators if g.current_user != cert.user: owner_role = role_service.get_by_name(cert.owner) permission = CertificatePermission(owner_role, [x.name for x in cert.roles]) if not permission.can(): return dict( message='You are not authorized to update this certificate' ), 403 for destination in data['destinations']: if destination.plugin.requires_key: if not cert.private_key: return dict( message= 'Unable to add destination: {0}. Certificate does not have required private key.' .format(destination.label)), 400 cert = service.update(certificate_id, **data) log_service.create(g.current_user, 'update_cert', certificate=cert) return cert
def put(self, certificate_id): """ .. http:put:: /certificates/1 Update a certificate **Example request**: .. sourcecode:: http PUT /certificates/1 HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "owner": "*****@*****.**", "active": false "notifications": [], "destinations": [], "replacements": [] } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "id": 1, "name": "cert1", "description": "this is cert1", "bits": 2048, "deleted": false, "issuer": "ExampeInc.", "serial": "123450", "chain": "-----Begin ...", "body": "-----Begin ...", "san": true, "owner": "*****@*****.**", "active": false, "notBefore": "2015-06-05T17:09:39", "notAfter": "2015-06-10T17:09:39", "cn": "example.com", "status": "unknown", } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ self.reqparse.add_argument('active', type=bool, location='json') self.reqparse.add_argument('owner', type=str, location='json') self.reqparse.add_argument('description', type=str, location='json') self.reqparse.add_argument('destinations', type=list, default=[], location='json') self.reqparse.add_argument('notifications', type=notification_list, default=[], location='json') self.reqparse.add_argument('replacements', type=list, default=[], location='json') args = self.reqparse.parse_args() cert = service.get(certificate_id) role = role_service.get_by_name(cert.owner) permission = UpdateCertificatePermission(certificate_id, getattr(role, 'name', None)) if permission.can(): return service.update( certificate_id, args['owner'], args['description'], args['active'], args['destinations'], args['notifications'], args['replacements'] ) return dict(message='You are not authorized to update this certificate'), 403
def run(self, password): create() user = user_service.get_by_username("lemur") admin_role = role_service.get_by_name("admin") if admin_role: sys.stdout.write("[-] Admin role already created, skipping...!\n") else: # we create an admin role admin_role = role_service.create( "admin", description="This is the Lemur administrator role.") sys.stdout.write("[+] Created 'admin' role\n") operator_role = role_service.get_by_name("operator") if operator_role: sys.stdout.write( "[-] Operator role already created, skipping...!\n") else: # we create an operator role operator_role = role_service.create( "operator", description="This is the Lemur operator role.") sys.stdout.write("[+] Created 'operator' role\n") read_only_role = role_service.get_by_name("read-only") if read_only_role: sys.stdout.write( "[-] Read only role already created, skipping...!\n") else: # we create an read only role read_only_role = role_service.create( "read-only", description="This is the Lemur read only role.") sys.stdout.write("[+] Created 'read-only' role\n") if not user: if not password: sys.stdout.write( "We need to set Lemur's password to continue!\n") password = prompt_pass("Password") password1 = prompt_pass("Confirm Password") if password != password1: sys.stderr.write("[!] Passwords do not match!\n") sys.exit(1) user_service.create("lemur", password, "*****@*****.**", True, None, [admin_role]) sys.stdout.write( "[+] Created the user 'lemur' and granted it the 'admin' role!\n" ) else: sys.stdout.write( "[-] Default user has already been created, skipping...!\n") intervals = current_app.config.get( "LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS", []) sys.stdout.write( "[!] Creating {num} notifications for {intervals} days as specified by LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS\n" .format(num=len(intervals), intervals=",".join([str(x) for x in intervals]))) recipients = current_app.config.get("LEMUR_SECURITY_TEAM_EMAIL") sys.stdout.write("[+] Creating expiration email notifications!\n") sys.stdout.write( "[!] Using {0} as specified by LEMUR_SECURITY_TEAM_EMAIL for notifications\n" .format(recipients)) notification_service.create_default_expiration_notifications( "DEFAULT_SECURITY", recipients=recipients) _DEFAULT_ROTATION_INTERVAL = "default" default_rotation_interval = policy_service.get_by_name( _DEFAULT_ROTATION_INTERVAL) if default_rotation_interval: sys.stdout.write( "[-] Default rotation interval policy already created, skipping...!\n" ) else: days = current_app.config.get("LEMUR_DEFAULT_ROTATION_INTERVAL", 30) sys.stdout.write( "[+] Creating default certificate rotation policy of {days} days before issuance.\n" .format(days=days)) policy_service.create(days=days, name=_DEFAULT_ROTATION_INTERVAL) sys.stdout.write("[/] Done!\n")
def post(self): self.reqparse.add_argument('clientId', type=str, required=True, location='json') self.reqparse.add_argument('redirectUri', type=str, required=True, location='json') self.reqparse.add_argument('code', type=str, required=True, location='json') args = self.reqparse.parse_args() # take the information we have received from the provider to create a new request params = { 'client_id': args['clientId'], 'grant_type': 'authorization_code', 'scope': 'openid email profile address', 'redirect_uri': args['redirectUri'], 'code': args['code'] } # you can either discover these dynamically or simply configure them access_token_url = current_app.config.get('PING_ACCESS_TOKEN_URL') user_api_url = current_app.config.get('PING_USER_API_URL') # the secret and cliendId will be given to you when you signup for the provider basic = base64.b64encode('{0}:{1}'.format(args['clientId'], current_app.config.get("PING_SECRET"))) headers = {'Authorization': 'Basic {0}'.format(basic)} # exchange authorization code for access token. r = requests.post(access_token_url, headers=headers, params=params) id_token = r.json()['id_token'] access_token = r.json()['access_token'] # fetch token public key header_data = fetch_token_header(id_token) jwks_url = current_app.config.get('PING_JWKS_URL') # retrieve the key material as specified by the token header r = requests.get(jwks_url) for key in r.json()['keys']: if key['kid'] == header_data['kid']: secret = get_rsa_public_key(key['n'], key['e']) algo = header_data['alg'] break else: return dict(message='Key not found'), 403 # validate your token based on the key it was signed with try: jwt.decode(id_token, secret, algorithms=[algo], audience=args['clientId']) except jwt.DecodeError: return dict(message='Token is invalid'), 403 except jwt.ExpiredSignatureError: return dict(message='Token has expired'), 403 except jwt.InvalidTokenError: return dict(message='Token is invalid'), 403 user_params = dict(access_token=access_token, schema='profile') # retrieve information about the current user. r = requests.get(user_api_url, params=user_params) profile = r.json() user = user_service.get_by_email(profile['email']) # update their google 'roles' roles = [] for group in profile['googleGroups']: role = role_service.get_by_name(group) if not role: role = role_service.create(group, description='This is a google group based role created by Lemur') roles.append(role) # if we get an sso user create them an account # we still pick a random password in case sso is down if not user: # every user is an operator (tied to a default role) if current_app.config.get('LEMUR_DEFAULT_ROLE'): v = role_service.get_by_name(current_app.config.get('LEMUR_DEFAULT_ROLE')) if v: roles.append(v) user = user_service.create( profile['email'], get_psuedo_random_string(), profile['email'], True, profile.get('thumbnailPhotoUrl'), roles ) else: # we add 'lemur' specific roles, so they do not get marked as removed for ur in user.roles: if ur.authority_id: roles.append(ur) # update any changes to the user user_service.update( user.id, profile['email'], profile['email'], True, profile.get('thumbnailPhotoUrl'), # incase profile isn't google+ enabled roles ) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) return dict(token=create_token(user))
def put(self, authority_id, data=None): """ .. http:put:: /authorities/1 Update a authority **Example request**: .. sourcecode:: http PUT /authorities/1 HTTP/1.1 Host: example.com Accept: application/json, text/javascript { "roles": [], "active": false, "owner": "*****@*****.**", "description": "this is authority1" } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript { "id": 1, "name": "authority1", "description": "this is authority1", "pluginName": null, "chain": "-----begin ...", "body": "-----begin ...", "active": false, "notBefore": "2015-06-05t17:09:39", "notAfter": "2015-06-10t17:09:39" "options": null } :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error :statuscode 403: unauthenticated """ authority = service.get(authority_id) if not authority: return dict(message='Not Found'), 404 role = role_service.get_by_name(authority.owner) # all the authority role members should be allowed roles = [x.name for x in authority.roles] # allow "owner" roles by team DL roles.append(role) permission = AuthorityPermission(authority_id, roles) # we want to make sure that we cannot add roles that we are not members of if not g.current_user.is_admin: role_ids = set([r.id for r in data['roles']]) user_role_ids = set([r.id for r in g.current_user.roles]) if not role_ids.issubset(user_role_ids): return dict(message="You are not allowed to associate a role which you are not a member of"), 400 if permission.can(): return service.update( authority_id, owner=data['owner'], description=data['description'], active=data['active'], roles=data['roles'] ) return dict(message="You are not authorized to update this authority"), 403
def create(kwargs): """ Create a new authority. :return: """ issuer = plugins.get(kwargs.get('pluginName')) kwargs['creator'] = g.current_user.email cert_body, intermediate, issuer_roles = issuer.create_authority(kwargs) cert = Certificate(cert_body, chain=intermediate) cert.owner = kwargs['ownerEmail'] if kwargs['caType'] == 'subca': cert.description = "This is the ROOT certificate for the {0} sub certificate authority the parent \ authority is {1}.".format(kwargs.get('caName'), kwargs.get('caParent')) else: cert.description = "This is the ROOT certificate for the {0} certificate authority.".format( kwargs.get('caName') ) cert.user = g.current_user cert.notifications = notification_service.create_default_expiration_notifications( 'DEFAULT_SECURITY', current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL') ) # we create and attach any roles that the issuer gives us role_objs = [] for r in issuer_roles: role = role_service.create( r['name'], password=r['password'], description="{0} auto generated role".format(kwargs.get('pluginName')), username=r['username']) # the user creating the authority should be able to administer it if role.username == 'admin': g.current_user.roles.append(role) role_objs.append(role) authority = Authority( kwargs.get('caName'), kwargs['ownerEmail'], kwargs['pluginName'], cert_body, description=kwargs['caDescription'], chain=intermediate, roles=role_objs ) database.update(cert) authority = database.create(authority) # the owning dl or role should have this authority associated with it owner_role = role_service.get_by_name(kwargs['ownerEmail']) if not owner_role: owner_role = role_service.create(kwargs['ownerEmail']) owner_role.authority = authority g.current_user.authorities.append(authority) return authority