Skip to content

Commit

Permalink
Release 1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
3keyroman authored Feb 9, 2023
2 parents d1c646d + 04287a0 commit ae03c10
Show file tree
Hide file tree
Showing 11 changed files with 2,986 additions and 2,885 deletions.
16 changes: 11 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,21 @@ WORKDIR $WRK_DIR
# Toggle CGO based on your app requirement. CGO_ENABLED=1 for enabling CGO
RUN CGO_ENABLED=0 go build -ldflags '-s -w -extldflags "-static"' -o $WRK_DIR/appbin $WRK_DIR

COPY docker /app/docker

#
# Run Stage
#
FROM alpine:3.15

ENV WRK_DIR /app
COPY --from=builder $WRK_DIR $WRK_DIR
# add non root user czertainly
RUN addgroup --system --gid 10001 czertainly && adduser --system --home /opt/czertainly --uid 10001 --ingroup czertainly czertainly

WORKDIR $WRK_DIR
COPY --from=builder /app/docker /
COPY --from=builder /app /opt/czertainly

WORKDIR /opt/czertainly

USER 10001

# Start the app
CMD ["./appbin"]
ENTRYPOINT ["/opt/czertainly/entry.sh"]
19 changes: 8 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
X509 Compliance `Connector` is the implementation of the following `Function Groups` and `Kinds`:

| Function Group | Kind |
| --- | --- |
| Function Group | Kind |
|-----------------------|--------|
| `Compliance Provider` | `x509` |

X509 Compliance Provider is the implementation of compliance check and management for x509 certificates that are managed by CZERTAINLY. This `Connector` performs compliance check for the certificates of type x509. List of items to be considered to determine the compliance of a certificate is administrated by the rules and groups.
Expand All @@ -18,24 +18,21 @@ Rules in the X509 Compliance Provider describes the condition that should be app

Groups are the logical grouping of the rules organized by some baseline similarities. A group may contain two or more rules and when a compliance profile is added with the group, all the rules in the group will be applied to the certificate compliance determination


X509 Compliance Provider allows you to perform the following operations:
- Check compliance of x509 Certificate

## Database requirements

This `Connector` does not require any database as it does not store any information
This `Connector` does not require any database as it does not persist any data.

## Short Process Description

Compliance of the certificate is calculated by the use of `Compliance Profiles`. `Compliance Profiles` are the entities that holds the list of rules and groups to be considered for the compliance calculation. These objects holds rules and groups from different `Connectors`, apply them accordingly and compute the status based on the rule validations.

X509 Compliance Provider consumes ZLint for some rules and groups. To know more about ZLint, refer to [ZLint](https://github.com/zmap/zlint)


To know more about the `Core`, refer to [CZERTAINLY Core](https://github.com/3KeyCompany/CZERTAINLY-Core)


## Interfaces

X509 Compliance `Connector` implements `Compliance Provider` interfaces. To learn more about the interfaces and end points, refer to the [CZERTAINLY Interfaces](https://github.com/3KeyCompany/CZERTAINLY-Interfaces).
Expand All @@ -44,9 +41,9 @@ For more information, please refer to the [CZERTAINLY documentation](https://doc

## Docker container

X509 Compliance `Connector` is provided as a Docker container. Use the `3keycompany/czertainly-x509-compliance-provider:tagname` to pull the required image from the repository. It can be configured using the following environment variables:
X509 Compliance `Connector` is provided as a Docker container. Use the `harbor.3key.company/czertainly/czertainly-x509-compliance-provider:tagname` to pull the required image from the repository. It can be configured using the following environment variables:

| Variable | Description | Required | Default value |
| --- | --- | --- | --- |
| `SERVER_PORT` | Port where the service is exposed | No | 8080 |
| `LOG_LEVEL` | Logging level for the service | No | INFO |
| Variable | Description | Required | Default value |
|---------------|-----------------------------------|-----------------------------------------------|---------------|
| `SERVER_PORT` | Port where the service is exposed | ![](https://img.shields.io/badge/-NO-red.svg) | `8080` |
| `LOG_LEVEL` | Logging level for the service | ![](https://img.shields.io/badge/-NO-red.svg) | `INFO` |
50 changes: 31 additions & 19 deletions cmd/attributes/attributes.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,51 @@
package attributes

type AttributeType string
type AttributeContentType string

// AttributeType constants. These are the types of attributes that can be used in the rules.
const (
STRING AttributeType = "string"
INTEGER AttributeType = "integer"
BOOLEAN AttributeType = "boolean"
STRING AttributeContentType = "string"
INTEGER AttributeContentType = "integer"
BOOLEAN AttributeContentType = "boolean"
)

const (
DATA AttributeType = "data"
INFO AttributeType = "group"
GROUP AttributeType = "info"
)

// Attribute is a single attribute that can be used in the rules.
type (
Attributes struct {
UUID string `json:"uuid,omitempty"`
Name string `json:"name,omitempty"`
Label string `json:"label,omitempty"`
Type AttributeType `json:"type,omitempty"`
Required bool `json:"required,omitempty"`
ReadOnly bool `json:"readOnly,omitempty"`
Editable bool `json:"editable,omitempty"`
Visible bool `json:"visible,omitempty"`
MultiSelect bool `json:"multiSelect,omitempty"`
Description bool `json:"description,omitempty"`
Content interface{} `json:"content,omitempty"`
List bool `json:"list"`
UUID string `json:"uuid,omitempty"`
Name string `json:"name,omitempty"`
Type AttributeType `json:"type,omitempty"`
ContentType AttributeContentType `json:"content_type,omitempty"`
Description string `json:"description,omitempty"`
Properties AttributeProperties `json:"properties,omitempty"`
Content []BaseAttributeContent `json:"content,omitempty"`
}

AttributeProperties struct {
Label string `json:"label,omitempty"`
Required bool `json:"required,omitempty"`
ReadOnly bool `json:"readOnly,omitempty"`
Editable bool `json:"editable,omitempty"`
Visible bool `json:"visible,omitempty"`
MultiSelect bool `json:"multi,omitempty"`
List bool `json:"list"`
}

// BaseAttributeContent for the values of attributes
BaseAttributeContent struct {
Value interface{} `json:"value"`
Data interface{} `json:"data,omitempty"`
}

RequestAttributes struct {
Name string `json:"name"`
UUID string `json:"uuid"`
Content interface{} `json:"content"`
Name string `json:"name"`
UUID string `json:"uuid"`
Content []BaseAttributeContent `json:"content"`
}
)
6 changes: 3 additions & 3 deletions cmd/compliance/compliance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ func TestService_ComplianceCheckAttributes(t *testing.T) {
attrs := []attributes.RequestAttributes{{
Name: "condition",
UUID: "7ed00782-e706-11ec-8fea-0242ac120002",
Content: attributes.BaseAttributeContent{Value: "Equals"}},
Content: []attributes.BaseAttributeContent{{Data: "Equals"}}},
{
Name: "length",
UUID: "7ed00886-e706-11ec-8fea-0242ac120002",
Content: attributes.BaseAttributeContent{Value: 2048},
}}
Content: []attributes.BaseAttributeContent{{Data: 2048}}},
}
rules := []RequestRules{{
UUID: "7ed00480-e706-11ec-8fea-0242ac120002",
Attributes: attrs,
Expand Down
16 changes: 8 additions & 8 deletions cmd/compliance/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ func boolToRuleStatusMapper(boolData bool) (status rules.RuleStatus) {

// HashAlgorithmValidation validates the hash algorithm of the certificate
func HashingAlgorithmValidation(certificate *x509.Certificate, requestRule RequestRules, request Request, ruleDefinition rules.RuleDefinition) ResponseRules {
condition := utils.GetRequestAttributeValue("condition", requestRule.Attributes)
value := utils.GetRequestAttributeValue("algorithm", requestRule.Attributes)
condition := utils.GetRequestAttributeValue("condition", requestRule.Attributes, true)
value := utils.GetRequestAttributeValue("algorithm", requestRule.Attributes, true)

mappings := map[string]string{"MD5WITHRSA": "MD5-RSA", "SHA1WITHRSA": "SHA1-RSA", "SHA224WITHRSA": "SHA224-RSA", "SHA256WITHRSA": "SHA256-RSA", "SHA384WITHRSA": "SHA384-RSA", "SHA512WITHRSA": "SHA512-RSA", "SHA1WITHECDSA": "ECDSA-SHA1", "SHA224WITHECDSA": "ECDSA-SHA224", "SHA256WITHECDSA": "ECDSA-SHA256", "SHA384WITHECDSA": "ECDSA-SHA384", "SHA512WITHECDSA": "ECDSA-SHA512"}

Expand All @@ -40,8 +40,8 @@ func HashingAlgorithmValidation(certificate *x509.Certificate, requestRule Reque

// PublicKeyAlgorithmValidation validates the public key algorithm of the certificate
func PublicKeyAlgorithmValidation(certificate *x509.Certificate, requestRule RequestRules, request Request, ruleDefinition rules.RuleDefinition) ResponseRules {
condition := utils.GetRequestAttributeValue("condition", requestRule.Attributes)
value := utils.GetRequestAttributeValue("algorithm", requestRule.Attributes)
condition := utils.GetRequestAttributeValue("condition", requestRule.Attributes, true)
value := utils.GetRequestAttributeValue("algorithm", requestRule.Attributes, true)
pubKeyAlgorithm := certificate.PublicKeyAlgorithmName()
isAlgorithmAvailable := utils.Contains(utils.InterfaceAsStringArray(value), pubKeyAlgorithm)
switch condition {
Expand All @@ -55,8 +55,8 @@ func PublicKeyAlgorithmValidation(certificate *x509.Certificate, requestRule Req

// EccCurveValidation validates the curve of the certificate
func EcCurveValidation(certificate *x509.Certificate, requestRule RequestRules, request Request, ruleDefinition rules.RuleDefinition) ResponseRules {
condition := utils.GetRequestAttributeValue("condition", requestRule.Attributes)
value := utils.GetRequestAttributeValue("algorithm", requestRule.Attributes)
condition := utils.GetRequestAttributeValue("condition", requestRule.Attributes, true)
value := utils.GetRequestAttributeValue("algorithm", requestRule.Attributes, true)
curve := certificate.PublicKey.(*x509.AugmentedECDSA).Pub.Curve.Params().Name
isValid := utils.Contains(utils.InterfaceAsStringArray(value), curve)
switch condition {
Expand All @@ -70,8 +70,8 @@ func EcCurveValidation(certificate *x509.Certificate, requestRule RequestRules,

// KeySizeValidation validates the key size of the certificate
func KeySizeValidator(certificate *x509.Certificate, requestRule RequestRules, request Request, ruleDefinition rules.RuleDefinition) ResponseRules {
condition := utils.GetRequestAttributeValue("condition", requestRule.Attributes)
value := utils.InterfaceAsInteger(utils.GetRequestAttributeValue("length", requestRule.Attributes))
condition := utils.GetRequestAttributeValue("condition", requestRule.Attributes, true)
value := utils.InterfaceAsInteger(utils.GetRequestAttributeValue("length", requestRule.Attributes, true))
keySize := utils.GetPublicKeySize(certificate)

switch condition {
Expand Down
36 changes: 19 additions & 17 deletions cmd/utils/attributedefinition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

func TestGetRequestAttributeValue(t *testing.T) {
attrValue := attributes.BaseAttributeContent{Value: "testing"}
attrValue := []attributes.BaseAttributeContent{{Data: "testing"}}
attrs := []attributes.Attributes{
attributes.Attributes{
UUID: "df52f720-f239-11ec-b939-0242ac120002",
Expand All @@ -15,33 +15,35 @@ func TestGetRequestAttributeValue(t *testing.T) {
},
}

valueOfAttribute := GetAttributeValue("Test", attrs)
if valueOfAttribute != attrValue {
valueOfAttribute := GetAttributeValue("Test", attrs, true)
if valueOfAttribute != attrValue[0].Data {
t.Error("Attribute Value fetch failed")
}
}

func TestGetAttributeValue(t *testing.T) {
attrValue := attributes.BaseAttributeContent{Value: "testing"}
attrValue := []attributes.BaseAttributeContent{{Data: "testing"}}
attrs := []attributes.Attributes{
attributes.Attributes{
UUID: "df52f720-f239-11ec-b939-0242ac120002",
Name: "Test",
Label: "Test",
Type: "STRING",
Required: false,
ReadOnly: false,
Editable: false,
Visible: false,
MultiSelect: false,
Description: false,
UUID: "df52f720-f239-11ec-b939-0242ac120002",
Name: "Test",
Type: "STRING",
Properties: attributes.AttributeProperties{
Label: "Test",
Required: false,
ReadOnly: false,
Editable: false,
Visible: false,
MultiSelect: false,
List: false,
},
Description: "",
Content: attrValue,
List: false,
},
}

valueOfAttribute := GetAttributeValue("Test", attrs)
if valueOfAttribute != attrValue {
valueOfAttribute := GetAttributeValue("Test", attrs, true)
if valueOfAttribute != attrValue[0].Data {
t.Error("Attribute Value fetch failed")
}
}
12 changes: 9 additions & 3 deletions cmd/utils/attributedefinitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,32 @@ package utils
import "CZERTAINLY-X509-Compliance-Provider/cmd/attributes"

// GetAttributeValue returns the value of the attribute with the given name.
func GetAttributeValue(attributeName string, attributes []attributes.Attributes) (value interface{}) {
func GetAttributeValue(attributeName string, attributes []attributes.Attributes, returnSingleEntry bool) (value interface{}) {
if len(attributes) == 0 {
return nil
}
for _, attribute := range attributes {
if attribute.Name == attributeName {
if returnSingleEntry {
return attribute.Content[0].Data
}
return attribute.Content
}
}
return nil
}

// GetRequiredAttributeValue returns the value of the required attribute with the given name.
func GetRequestAttributeValue(attributeName string, attrs []attributes.RequestAttributes) (value interface{}) {
func GetRequestAttributeValue(attributeName string, attrs []attributes.RequestAttributes, returnSingleEntry bool) (value interface{}) {
if len(attrs) == 0 {
return nil
}
for _, attribute := range attrs {
if attribute.Name == attributeName {
return (attribute.Content).(map[string]interface{})["value"]
if returnSingleEntry {
return attribute.Content[0].Data
}
return attribute.Content
}
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ server:

# Logger related configurations
log:
level: INFO
level: PANIC
9 changes: 9 additions & 0 deletions docker/opt/czertainly/entry.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh

czertainlyHome="/opt/czertainly"
source ${czertainlyHome}/static-functions

log "INFO" "Launching X.509 Compliance Provider"
./appbin

#exec "$@"
17 changes: 17 additions & 0 deletions docker/opt/czertainly/static-functions
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

log() {
# 2022-02-08 15:49:15
dateString="$(date +%F' '%T)"
logLevel=$(printf '%-5s' "${1:-INFO}")
className="$0"
processId="$$"
#threadId="$(ps H -o 'tid' $processId | tail -n 1| tr -d ' ')"
if [ -z "$2" ] ; then
while read line ; do
echo "[$dateString] $logLevel [$className] (process:$processId) ${line}"
done
else
echo "[$dateString] $logLevel [$className] (process:$processId) ${2}"
fi
}
Loading

0 comments on commit ae03c10

Please sign in to comment.