diff --git a/docs/docs.go b/docs/docs.go index 4f4f6ef..b6c60bc 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -108,6 +108,15 @@ const docTemplate = `{ "CA" ], "summary": "Certificate Authorities (CA) Information based in Common Name", + "parameters": [ + { + "type": "string", + "description": "Common Name", + "name": "cn", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -140,6 +149,15 @@ const docTemplate = `{ "CA/{CN}/Certificates" ], "summary": "List all Certificates managed by a certain Certificate Authority", + "parameters": [ + { + "type": "string", + "description": "Common Name of the Certificate Authority", + "name": "cn", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -174,6 +192,13 @@ const docTemplate = `{ ], "summary": "CA issue new certificate", "parameters": [ + { + "type": "string", + "description": "Common Name of the Certificate Authority", + "name": "cn", + "in": "path", + "required": true + }, { "description": "Add new Certificate Authority or Intermediate Certificate Authority", "name": "ca", @@ -216,6 +241,22 @@ const docTemplate = `{ "CA/{CN}/Certificates" ], "summary": "Get information about a Certificate", + "parameters": [ + { + "type": "string", + "description": "Common Name of the Certificate Authority", + "name": "cn", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Common Name of Certificate", + "name": "certificate_cn", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -249,6 +290,22 @@ const docTemplate = `{ "CA/{CN}/Certificates" ], "summary": "CA revoke a existent certificate managed by CA", + "parameters": [ + { + "type": "string", + "description": "Common Name of the Certificate Authority", + "name": "cn", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Common Name of Certificate", + "name": "certificate_cn", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -427,77 +484,6 @@ const docTemplate = `{ } } }, - "goca.Identity": { - "type": "object", - "properties": { - "country": { - "description": "Country (two letters)", - "type": "string", - "example": "NL" - }, - "dns_names": { - "description": "DNS Names list", - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "ca.example.com", - "root-ca.example.com" - ] - }, - "email": { - "description": "Email Address", - "type": "string", - "example": "sec@company.com" - }, - "intermediate": { - "description": "Intermendiate Certificate Authority (default is false)", - "type": "boolean", - "example": false - }, - "ip_addresses": { - "description": "IP Address list", - "type": "array", - "items": { - "type": "array", - "items": { - "type": "integer" - } - } - }, - "key_size": { - "description": "Key Bit Size (defaul: 2048)", - "type": "integer", - "example": 2048 - }, - "locality": { - "description": "Locality name", - "type": "string", - "example": "Noord-Brabant" - }, - "organization": { - "description": "Organization name", - "type": "string", - "example": "Company" - }, - "organization_unit": { - "description": "Organizational Unit name", - "type": "string", - "example": "Security Management" - }, - "province": { - "description": "Province name", - "type": "string", - "example": "Veldhoven" - }, - "valid": { - "description": "Minimum 1 day, maximum 825 days -- Default: 397", - "type": "integer", - "example": 365 - } - } - }, "models.CABody": { "type": "object", "properties": { @@ -539,6 +525,16 @@ const docTemplate = `{ "intermediate": { "type": "boolean" }, + "ip_addresses": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "127.0.0.1", + "192.168.2.1" + ] + }, "issue_date": { "type": "string", "example": "2021-01-06 10:31:43 +0000 UTC" @@ -587,6 +583,16 @@ const docTemplate = `{ "files": { "$ref": "#/definitions/goca.Certificate" }, + "ip_addresses": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "127.0.0.1", + "192.168.0.1" + ] + }, "issue_date": { "type": "string", "example": "2021-01-06 10:31:43 +0000 UTC" @@ -598,7 +604,96 @@ const docTemplate = `{ } }, "models.Payload": { - "type": "object" + "type": "object", + "required": [ + "common_name", + "identity" + ], + "properties": { + "common_name": { + "type": "string", + "example": "root-ca" + }, + "identity": { + "$ref": "#/definitions/models.PayloadIdentity" + }, + "parent_common_name": { + "type": "string", + "example": "root-ca" + } + } + }, + "models.PayloadIdentity": { + "type": "object", + "properties": { + "country": { + "description": "Country (two letters)", + "type": "string", + "example": "NL" + }, + "dns_names": { + "description": "DNS Names list", + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "ca.example.com", + "root-ca.example.com" + ] + }, + "email": { + "description": "Email Address", + "type": "string", + "example": "sec@company.com" + }, + "intermediate": { + "description": "Intermendiate Certificate Authority (default is false)", + "type": "boolean", + "example": false + }, + "ip_addresses": { + "description": "IP Address list", + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "127.0.0.1", + "192.168.0.1" + ] + }, + "key_size": { + "description": "Key Bit Size (defaul: 2048)", + "type": "integer", + "example": 2048 + }, + "locality": { + "description": "Locality name", + "type": "string", + "example": "Noord-Brabant" + }, + "organization": { + "description": "Organization name", + "type": "string", + "example": "Company" + }, + "organization_unit": { + "description": "Organizational Unit name", + "type": "string", + "example": "Security Management" + }, + "province": { + "description": "Province name", + "type": "string", + "example": "Veldhoven" + }, + "valid": { + "description": "Minimum 1 day, maximum 825 days -- Default: 397", + "type": "integer", + "example": 365 + } + } }, "models.ResponseCA": { "type": "object", diff --git a/docs/swagger.json b/docs/swagger.json index 8b718d1..5d89800 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -103,6 +103,15 @@ "CA" ], "summary": "Certificate Authorities (CA) Information based in Common Name", + "parameters": [ + { + "type": "string", + "description": "Common Name", + "name": "cn", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -135,6 +144,15 @@ "CA/{CN}/Certificates" ], "summary": "List all Certificates managed by a certain Certificate Authority", + "parameters": [ + { + "type": "string", + "description": "Common Name of the Certificate Authority", + "name": "cn", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -169,6 +187,13 @@ ], "summary": "CA issue new certificate", "parameters": [ + { + "type": "string", + "description": "Common Name of the Certificate Authority", + "name": "cn", + "in": "path", + "required": true + }, { "description": "Add new Certificate Authority or Intermediate Certificate Authority", "name": "ca", @@ -211,6 +236,22 @@ "CA/{CN}/Certificates" ], "summary": "Get information about a Certificate", + "parameters": [ + { + "type": "string", + "description": "Common Name of the Certificate Authority", + "name": "cn", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Common Name of Certificate", + "name": "certificate_cn", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -244,6 +285,22 @@ "CA/{CN}/Certificates" ], "summary": "CA revoke a existent certificate managed by CA", + "parameters": [ + { + "type": "string", + "description": "Common Name of the Certificate Authority", + "name": "cn", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Common Name of Certificate", + "name": "certificate_cn", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -422,77 +479,6 @@ } } }, - "goca.Identity": { - "type": "object", - "properties": { - "country": { - "description": "Country (two letters)", - "type": "string", - "example": "NL" - }, - "dns_names": { - "description": "DNS Names list", - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "ca.example.com", - "root-ca.example.com" - ] - }, - "email": { - "description": "Email Address", - "type": "string", - "example": "sec@company.com" - }, - "intermediate": { - "description": "Intermendiate Certificate Authority (default is false)", - "type": "boolean", - "example": false - }, - "ip_addresses": { - "description": "IP Address list", - "type": "array", - "items": { - "type": "array", - "items": { - "type": "integer" - } - } - }, - "key_size": { - "description": "Key Bit Size (defaul: 2048)", - "type": "integer", - "example": 2048 - }, - "locality": { - "description": "Locality name", - "type": "string", - "example": "Noord-Brabant" - }, - "organization": { - "description": "Organization name", - "type": "string", - "example": "Company" - }, - "organization_unit": { - "description": "Organizational Unit name", - "type": "string", - "example": "Security Management" - }, - "province": { - "description": "Province name", - "type": "string", - "example": "Veldhoven" - }, - "valid": { - "description": "Minimum 1 day, maximum 825 days -- Default: 397", - "type": "integer", - "example": 365 - } - } - }, "models.CABody": { "type": "object", "properties": { @@ -534,6 +520,16 @@ "intermediate": { "type": "boolean" }, + "ip_addresses": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "127.0.0.1", + "192.168.2.1" + ] + }, "issue_date": { "type": "string", "example": "2021-01-06 10:31:43 +0000 UTC" @@ -582,6 +578,16 @@ "files": { "$ref": "#/definitions/goca.Certificate" }, + "ip_addresses": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "127.0.0.1", + "192.168.0.1" + ] + }, "issue_date": { "type": "string", "example": "2021-01-06 10:31:43 +0000 UTC" @@ -604,7 +610,7 @@ "example": "root-ca" }, "identity": { - "$ref": "#/definitions/goca.Identity" + "$ref": "#/definitions/models.PayloadIdentity" }, "parent_common_name": { "type": "string", @@ -612,6 +618,78 @@ } } }, + "models.PayloadIdentity": { + "type": "object", + "properties": { + "country": { + "description": "Country (two letters)", + "type": "string", + "example": "NL" + }, + "dns_names": { + "description": "DNS Names list", + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "ca.example.com", + "root-ca.example.com" + ] + }, + "email": { + "description": "Email Address", + "type": "string", + "example": "sec@company.com" + }, + "intermediate": { + "description": "Intermendiate Certificate Authority (default is false)", + "type": "boolean", + "example": false + }, + "ip_addresses": { + "description": "IP Address list", + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "127.0.0.1", + "192.168.0.1" + ] + }, + "key_size": { + "description": "Key Bit Size (defaul: 2048)", + "type": "integer", + "example": 2048 + }, + "locality": { + "description": "Locality name", + "type": "string", + "example": "Noord-Brabant" + }, + "organization": { + "description": "Organization name", + "type": "string", + "example": "Company" + }, + "organization_unit": { + "description": "Organizational Unit name", + "type": "string", + "example": "Security Management" + }, + "province": { + "description": "Province name", + "type": "string", + "example": "Veldhoven" + }, + "valid": { + "description": "Minimum 1 day, maximum 825 days -- Default: 397", + "type": "integer", + "example": 365 + } + } + }, "models.ResponseCA": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index e5588c0..15c18cd 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -57,60 +57,6 @@ definitions: -----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY----- type: string type: object - goca.Identity: - properties: - country: - description: Country (two letters) - example: NL - type: string - dns_names: - description: DNS Names list - example: - - ca.example.com - - root-ca.example.com - items: - type: string - type: array - email: - description: Email Address - example: sec@company.com - type: string - intermediate: - description: Intermendiate Certificate Authority (default is false) - example: false - type: boolean - ip_addresses: - description: IP Address list - items: - items: - type: integer - type: array - type: array - key_size: - description: 'Key Bit Size (defaul: 2048)' - example: 2048 - type: integer - locality: - description: Locality name - example: Noord-Brabant - type: string - organization: - description: Organization name - example: Company - type: string - organization_unit: - description: Organizational Unit name - example: Security Management - type: string - province: - description: Province name - example: Veldhoven - type: string - valid: - description: 'Minimum 1 day, maximum 825 days -- Default: 397' - example: 365 - type: integer - type: object models.CABody: properties: certificates: @@ -140,6 +86,13 @@ definitions: $ref: '#/definitions/goca.CAData' intermediate: type: boolean + ip_addresses: + example: + - 127.0.0.1 + - 192.168.2.1 + items: + type: string + type: array issue_date: example: 2021-01-06 10:31:43 +0000 UTC type: string @@ -174,6 +127,13 @@ definitions: type: string files: $ref: '#/definitions/goca.Certificate' + ip_addresses: + example: + - 127.0.0.1 + - 192.168.0.1 + items: + type: string + type: array issue_date: example: 2021-01-06 10:31:43 +0000 UTC type: string @@ -187,7 +147,7 @@ definitions: example: root-ca type: string identity: - $ref: '#/definitions/goca.Identity' + $ref: '#/definitions/models.PayloadIdentity' parent_common_name: example: root-ca type: string @@ -195,6 +155,61 @@ definitions: - common_name - identity type: object + models.PayloadIdentity: + properties: + country: + description: Country (two letters) + example: NL + type: string + dns_names: + description: DNS Names list + example: + - ca.example.com + - root-ca.example.com + items: + type: string + type: array + email: + description: Email Address + example: sec@company.com + type: string + intermediate: + description: Intermendiate Certificate Authority (default is false) + example: false + type: boolean + ip_addresses: + description: IP Address list + example: + - 127.0.0.1 + - 192.168.0.1 + items: + type: string + type: array + key_size: + description: 'Key Bit Size (defaul: 2048)' + example: 2048 + type: integer + locality: + description: Locality name + example: Noord-Brabant + type: string + organization: + description: Organization name + example: Company + type: string + organization_unit: + description: Organizational Unit name + example: Security Management + type: string + province: + description: Province name + example: Veldhoven + type: string + valid: + description: 'Minimum 1 day, maximum 825 days -- Default: 397' + example: 365 + type: integer + type: object models.ResponseCA: properties: data: @@ -286,6 +301,12 @@ paths: /api/v1/ca/{cn}: get: description: list the Certificate Authorities data + parameters: + - description: Common Name + in: path + name: cn + required: true + type: string produces: - application/json responses: @@ -308,6 +329,12 @@ paths: get: description: list all certificates managed by a certain Certificate Authority (cn) + parameters: + - description: Common Name of the Certificate Authority + in: path + name: cn + required: true + type: string produces: - application/json responses: @@ -331,6 +358,11 @@ paths: - application/json description: the Certificate Authority issues a new Certificate parameters: + - description: Common Name of the Certificate Authority + in: path + name: cn + required: true + type: string - description: Add new Certificate Authority or Intermediate Certificate Authority in: body name: ca @@ -360,6 +392,17 @@ paths: consumes: - application/json description: the Certificate Authority revokes a managed Certificate + parameters: + - description: Common Name of the Certificate Authority + in: path + name: cn + required: true + type: string + - description: Common Name of Certificate + in: path + name: certificate_cn + required: true + type: string produces: - application/json responses: @@ -380,6 +423,17 @@ paths: - CA/{CN}/Certificates get: description: get information about a certificate issued by a certain CA + parameters: + - description: Common Name of the Certificate Authority + in: path + name: cn + required: true + type: string + - description: Common Name of Certificate + in: path + name: certificate_cn + required: true + type: string produces: - application/json responses: diff --git a/rest-api/controllers/controllers.go b/rest-api/controllers/controllers.go index 3a337c8..05d5653 100644 --- a/rest-api/controllers/controllers.go +++ b/rest-api/controllers/controllers.go @@ -15,6 +15,7 @@ import ( storage "github.com/kairoaraujo/goca/v2/_storage" "github.com/kairoaraujo/goca/v2/cert" "github.com/kairoaraujo/goca/v2/rest-api/models" + "github.com/kairoaraujo/goca/v2/rest-api/utils" ) func getCAData(ca goca.CA) (body models.CABody) { @@ -36,6 +37,7 @@ func getCAData(ca goca.CA) (body models.CABody) { if certificate != nil { body.DNSNames = certificate.DNSNames + body.IPAddresses = utils.ParseIPs2Strings(certificate.IPAddresses) body.IssueDate = certificate.NotBefore.String() body.ExpireDate = certificate.NotAfter.String() crl := ca.GoCRL() @@ -58,6 +60,7 @@ func getCertificateData(certificate goca.Certificate) (body models.CertificateBo cert := certificate.GoCert() + body.IPAddresses = utils.ParseIPs2Strings(cert.IPAddresses) body.CommonName = cert.Subject.CommonName body.DNSNames = cert.DNSNames body.SerialNumber = cert.SerialNumber.String() @@ -73,6 +76,7 @@ func payloadInit(json models.Payload) (commonName, parentCommonName string, iden commonName = json.CommonName parentCommonName = json.ParentCommonName + identity = goca.Identity{ Organization: json.Identity.Organization, OrganizationalUnit: json.Identity.OrganizationalUnit, @@ -80,6 +84,7 @@ func payloadInit(json models.Payload) (commonName, parentCommonName string, iden Locality: json.Identity.Locality, Province: json.Identity.Province, DNSNames: json.Identity.DNSNames, + IPAddresses: utils.ParseStrings2IPs(json.Identity.IPAddresses), Intermediate: json.Identity.Intermediate, KeyBitSize: json.Identity.KeyBitSize, Valid: json.Identity.Valid, @@ -148,6 +153,7 @@ func AddCA(c *gin.Context) { // @Description list the Certificate Authorities data // @Tags CA // @Produce json +// @Param cn path string true "Common Name" // @Success 200 {object} models.ResponseCA // @Failure 404 {object} models.ResponseError // @Failure 500 Internal Server Error @@ -328,6 +334,7 @@ func SignCSR(c *gin.Context) { // @Description list all certificates managed by a certain Certificate Authority (cn) // @Tags CA/{CN}/Certificates // @Produce json +// @Param cn path string true "Common Name of the Certificate Authority" // @Success 200 {object} models.ResponseCA // @Failure 404 {object} models.ResponseError // @Failure 500 Internal Server Error @@ -354,6 +361,7 @@ func GetCertificates(c *gin.Context) { // @Tags CA/{CN}/Certificates // @Produce json // @Accept json +// @Param cn path string true "Common Name of the Certificate Authority" // @Param ca body models.Payload true "Add new Certificate Authority or Intermediate Certificate Authority" // @Success 200 {object} models.ResponseCertificates // @Failure 404 {object} models.ResponseError @@ -402,6 +410,8 @@ func IssueCertificates(c *gin.Context) { // @Description get information about a certificate issued by a certain CA // @Tags CA/{CN}/Certificates // @Produce json +// @Param cn path string true "Common Name of the Certificate Authority" +// @Param certificate_cn path string true "Common Name of Certificate" // @Success 200 {object} models.ResponseCertificates // @Failure 404 {object} models.ResponseError // @Failure 500 Internal Server Error @@ -437,6 +447,8 @@ func GetCertificatesCommonName(c *gin.Context) { // @Tags CA/{CN}/Certificates // @Produce json // @Accept json +// @Param cn path string true "Common Name of the Certificate Authority" +// @Param certificate_cn path string true "Common Name of Certificate" // @Success 200 {object} models.CABody // @Failure 404 {object} models.ResponseError // @Failure 500 Internal Server Error diff --git a/rest-api/models/models.go b/rest-api/models/models.go index 1b5589b..3d14229 100644 --- a/rest-api/models/models.go +++ b/rest-api/models/models.go @@ -21,9 +21,23 @@ type ResponseList struct { } type Payload struct { - CommonName string `json:"common_name" example:"root-ca" binding:"required"` - ParentCommonName string `json:"parent_common_name" example:"root-ca"` - Identity goca.Identity `json:"identity" binding:"required"` + CommonName string `json:"common_name" example:"root-ca" binding:"required"` + ParentCommonName string `json:"parent_common_name" example:"root-ca"` + Identity PayloadIdentity `json:"identity" binding:"required"` +} + +type PayloadIdentity struct { + Organization string `json:"organization" example:"Company"` // Organization name + OrganizationalUnit string `json:"organization_unit" example:"Security Management"` // Organizational Unit name + Country string `json:"country" example:"NL"` // Country (two letters) + Locality string `json:"locality" example:"Noord-Brabant"` // Locality name + Province string `json:"province" example:"Veldhoven"` // Province name + EmailAddresses string `json:"email" example:"sec@company.com"` // Email Address + DNSNames []string `json:"dns_names" example:"ca.example.com,root-ca.example.com"` // DNS Names list + IPAddresses []string `json:"ip_addresses,omitempty" example:"127.0.0.1,192.168.0.1"` // IP Address list + Intermediate bool `json:"intermediate" example:"false"` // Intermendiate Certificate Authority (default is false) + KeyBitSize int `json:"key_size" example:"2048"` // Key Bit Size (defaul: 2048) + Valid int `json:"valid" example:"365"` // Minimum 1 day, maximum 825 days -- Default: 397 } type CABody struct { @@ -34,6 +48,7 @@ type CABody struct { IssueDate string `json:"issue_date" example:"2021-01-06 10:31:43 +0000 UTC"` ExpireDate string `json:"expire_date" example:"2022-01-06 10:31:43 +0000 UTC"` DNSNames []string `json:"dns_names" example:"ca.example.ca,root-ca.example.com"` + IPAddresses []string `json:"ip_addresses" example:"127.0.0.1,192.168.2.1"` CSR bool `json:"csr" example:"false"` Certificates []string `json:"certificates" example:"intranet.example.com,w3.example.com"` CertificateRevocationList []string `json:"revoked_certificates" example:"38188836191244388427366318074605547405,338255903472757769326153358304310617728"` @@ -46,5 +61,6 @@ type CertificateBody struct { IssueDate string `json:"issue_date" example:"2021-01-06 10:31:43 +0000 UTC"` ExpireDate string `json:"expire_date" example:"2022-01-06 10:31:43 +0000 UTC"` DNSNames []string `json:"dns_names" example:"w3.intranet.go-root.ca,intranet.go-root.ca"` + IPAddresses []string `json:"ip_addresses" example:"127.0.0.1,192.168.0.1"` Files goca.Certificate `json:"files"` } diff --git a/rest-api/utils/utils.go b/rest-api/utils/utils.go new file mode 100644 index 0000000..02485aa --- /dev/null +++ b/rest-api/utils/utils.go @@ -0,0 +1,32 @@ +package utils + +import ( + "net" +) + +// Parse []string to []net.IP +func ParseStrings2IPs(ipStrings []string) []net.IP { + result := []net.IP{} + + for _, str := range ipStrings { + ip := net.ParseIP(str) + if ip == nil { + continue + } + + result = append(result, ip) + } + + return result +} + +// Parse []net.IP to []string +func ParseIPs2Strings(ips []net.IP) []string { + result := []string{} + + for _, ip := range ips { + result = append(result, ip.String()) + } + + return result +} diff --git a/rest-api/utils/utils_test.go b/rest-api/utils/utils_test.go new file mode 100644 index 0000000..fce7c5f --- /dev/null +++ b/rest-api/utils/utils_test.go @@ -0,0 +1,17 @@ +package utils + +import ( + "log" + "testing" +) + +func TestParseIP(t *testing.T) { + ips := ParseStrings2IPs([]string{ + "192.168.2.1", + "192.168.2.2", + }) + + log.Println(ips) + + log.Println(ParseIPs2Strings(ips)) +}