""" .. module: lemur.authorities.schemas :platform: unix :copyright: (c) 2018 by Netflix Inc., see AUTHORS for more :license: Apache, see LICENSE for more details. .. moduleauthor:: Kevin Glisson """ from flask import current_app from marshmallow import fields, validates_schema, pre_load, post_dump from marshmallow import validate from marshmallow.exceptions import ValidationError from lemur.schemas import ( PluginInputSchema, PluginOutputSchema, ExtensionSchema, AssociatedAuthoritySchema, AssociatedRoleSchema, ) from lemur.users.schemas import UserNestedOutputSchema from lemur.common.schema import LemurInputSchema, LemurOutputSchema from lemur.common import validators, missing from lemur.common.fields import ArrowDateTime from lemur.constants import CERTIFICATE_KEY_TYPES from lemur.plugins.base import plugins class AuthorityInputSchema(LemurInputSchema): name = fields.String(required=True) owner = fields.Email(required=True) description = fields.String() common_name = fields.String(required=True, validate=validators.common_name) validity_start = ArrowDateTime() validity_end = ArrowDateTime() validity_years = fields.Integer() # certificate body fields organizational_unit = fields.String( missing=lambda: current_app.config.get("LEMUR_DEFAULT_ORGANIZATIONAL_UNIT") ) organization = fields.String( missing=lambda: current_app.config.get("LEMUR_DEFAULT_ORGANIZATION") ) location = fields.String() country = fields.String( missing=lambda: current_app.config.get("LEMUR_DEFAULT_COUNTRY") ) state = fields.String(missing=lambda: current_app.config.get("LEMUR_DEFAULT_STATE")) # Creating a String field instead of Email to allow empty value email = fields.String() plugin = fields.Nested(PluginInputSchema) # signing related options type = fields.String(validate=validate.OneOf(["root", "subca"]), missing="root") parent = fields.Nested(AssociatedAuthoritySchema) signing_algorithm = fields.String( validate=validate.OneOf(["sha256WithRSA", "sha1WithRSA", "sha256WithECDSA", "SHA384withECDSA", "SHA512withECDSA"]), missing="sha256WithRSA", ) key_type = fields.String( validate=validate.OneOf(CERTIFICATE_KEY_TYPES), missing="RSA2048" ) key_name = fields.String() sensitivity = fields.String( validate=validate.OneOf(["medium", "high"]), missing="medium" ) serial_number = fields.Integer() first_serial = fields.Integer(missing=1) extensions = fields.Nested(ExtensionSchema) roles = fields.Nested(AssociatedRoleSchema(many=True)) @validates_schema def validate_dates(self, data): validators.dates(data) @validates_schema def validate_subca(self, data): if data["type"] == "subca": if not data.get("parent"): raise ValidationError( "If generating a subca, parent 'authority' must be specified." ) @pre_load def ensure_dates(self, data): return missing.convert_validity_years(data) class AuthorityUpdateSchema(LemurInputSchema): owner = fields.Email(required=True) description = fields.String() active = fields.Boolean(missing=True) roles = fields.Nested(AssociatedRoleSchema(many=True)) class RootAuthorityCertificateOutputSchema(LemurOutputSchema): __envelope__ = False id = fields.Integer() active = fields.Boolean() bits = fields.Integer() body = fields.String() chain = fields.String() description = fields.String() name = fields.String() cn = fields.String() not_after = fields.DateTime() not_before = fields.DateTime() owner = fields.Email() status = fields.Boolean() user = fields.Nested(UserNestedOutputSchema) class AuthorityOutputSchema(LemurOutputSchema): id = fields.Integer() description = fields.String() name = fields.String() owner = fields.Email() plugin = fields.Nested(PluginOutputSchema) active = fields.Boolean() options = fields.Dict() roles = fields.List(fields.Nested(AssociatedRoleSchema)) max_issuance_days = fields.Integer() default_validity_days = fields.Integer() authority_certificate = fields.Nested(RootAuthorityCertificateOutputSchema) @post_dump def handle_auth_certificate(self, cert): # Plugins may need to modify the cert object before returning it to the user plugin = plugins.get(cert['plugin']['slug']) plugin.wrap_auth_certificate(cert['authority_certificate']) class AuthorityNestedOutputSchema(LemurOutputSchema): __envelope__ = False id = fields.Integer() description = fields.String() name = fields.String() owner = fields.Email() plugin = fields.Nested(PluginOutputSchema) active = fields.Boolean() authority_certificate = fields.Nested(RootAuthorityCertificateOutputSchema, only=["not_after", "not_before"]) is_cab_compliant = fields.Boolean() max_issuance_days = fields.Integer() default_validity_days = fields.Integer() authority_update_schema = AuthorityUpdateSchema() authority_input_schema = AuthorityInputSchema() authority_output_schema = AuthorityOutputSchema() authorities_output_schema = AuthorityOutputSchema(many=True)