Beispiel #1
0
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
Beispiel #2
0
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))
Beispiel #3
0
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]
Beispiel #4
0
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]
Beispiel #5
0
    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)
Beispiel #6
0
    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
Beispiel #7
0
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
Beispiel #8
0
    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
Beispiel #9
0
    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
Beispiel #10
0
    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, "[email protected]", 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")
Beispiel #11
0
    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
Beispiel #12
0
    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
Beispiel #13
0
    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))
Beispiel #14
0
    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)(?=.*[[email protected]$!%*#?&])[A-Za-z\\[email protected]$!%*#?&]{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
Beispiel #15
0
    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": "[email protected]",
                 "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": "[email protected]",
                "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
Beispiel #16
0
    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": "[email protected]",
                "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": "[email protected]",
                          "helpMessage": "Comma delimited list of email addresses",
                          "validation": "^([\\w+-.%][email protected][\\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": "[email protected]",
                "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
Beispiel #17
0
    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, '[email protected]', 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")
Beispiel #18
0
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
Beispiel #19
0
    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": "[email protected]",
                 "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": "[email protected]",
                    "id": 1,
                    "description": "verisign test authority",
                    "name": "verisign"
                },
                "owner": "[email protected]",
                "serial": "82311058732025924142789179368889309156",
                "id": 2288,
                "issuer": "SymantecCorporation",
                "destinations": [],
                "description": null,
                "deleted": null,
                "notifications": [{
                    "id": 1
                }]
                "user": {
                    "username": "jane",
                    "active": true,
                    "email": "[email protected]",
                    "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": "[email protected]"
                }],
                "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
Beispiel #20
0
    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))
Beispiel #21
0
    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": "[email protected]",
                    "id": 1,
                    "description": "verisign test authority",
                    "name": "verisign"
                },
                "owner": "[email protected]",
                "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": "jane",
                    "active": true,
                    "email": "[email protected]",
                    "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": "[email protected]"
                }],
                "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
Beispiel #22
0
    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": "[email protected]",
                  "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": "[email protected]",
                    "id": 1,
                    "description": "verisign test authority",
                    "name": "verisign"
                },
                "owner": "[email protected]",
                "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": "jane",
                    "active": true,
                    "email": "[email protected]",
                    "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": "[email protected]"
                }],
                "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
Beispiel #23
0
    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": "[email protected]",
                 "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": "[email protected]",
                    "id": 1,
                    "description": "verisign test authority",
                    "name": "verisign"
                },
                "owner": "[email protected]",
                "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": "jane",
                    "active": true,
                    "email": "[email protected]",
                    "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": "[email protected]"
                }],
                "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
Beispiel #24
0
    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": "[email protected]",
                 "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
Beispiel #25
0
    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)(?=.*[[email protected]$!%*#?&])[A-Za-z\\[email protected]$!%*#?&]{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'))
Beispiel #26
0
    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))