Skip to content

Commit

Permalink
Package certificates:
Browse files Browse the repository at this point in the history
- rework package to allow convert config to model and retrive config from model
- add sub package to manage cipher, curves, auth client, tls version, certificates, root ca...
- add some small test (can be expande to having more coverage)
- optimize some code
  • Loading branch information
nabbar committed Dec 3, 2024
1 parent eca6890 commit b78fce5
Show file tree
Hide file tree
Showing 34 changed files with 3,098 additions and 486 deletions.
90 changes: 90 additions & 0 deletions certificates/auth/encode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/

package auth

import (
"fmt"

"gopkg.in/yaml.v3"
)

func (a *ClientAuth) unmarshall(val []byte) error {
*a = parseBytes(val)
return nil
}

func (a ClientAuth) MarshalJSON() ([]byte, error) {
t := a.String()
b := make([]byte, 0, len(t)+2)
b = append(b, '"')
b = append(b, []byte(t)...)
b = append(b, '"')
return b, nil
}

func (a *ClientAuth) UnmarshalJSON(bytes []byte) error {
return a.unmarshall(bytes)
}

func (a ClientAuth) MarshalYAML() (interface{}, error) {
return []byte(a.String()), nil
}

func (a *ClientAuth) UnmarshalYAML(value *yaml.Node) error {
return a.unmarshall([]byte(value.Value))
}

func (a ClientAuth) MarshalTOML() ([]byte, error) {
return []byte(a.String()), nil
}

func (a *ClientAuth) UnmarshalTOML(i interface{}) error {
if p, k := i.([]byte); k {
return a.unmarshall(p)
}
if p, k := i.(string); k {
return a.unmarshall([]byte(p))
}
return fmt.Errorf("tls client Auth: value not in valid format")
}

func (a ClientAuth) MarshalText() ([]byte, error) {
return []byte(a.String()), nil
}

func (a *ClientAuth) UnmarshalText(bytes []byte) error {
return a.unmarshall(bytes)
}

func (a ClientAuth) MarshalCBOR() ([]byte, error) {
return []byte(a.String()), nil
}

func (a *ClientAuth) UnmarshalCBOR(bytes []byte) error {
return a.unmarshall(bytes)
}
56 changes: 56 additions & 0 deletions certificates/auth/format.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/

package auth

import (
"crypto/tls"
"strings"
)

func (a ClientAuth) String() string {
switch a {
case RequireAndVerifyClientCert:
return strict + " " + require + " " + verify
case VerifyClientCertIfGiven:
return verify
case RequireAnyClientCert:
return require
case RequestClientCert:
return request
default:
return none
}
}

func (a ClientAuth) Code() string {
return strings.ToLower(a.String())
}

func (a ClientAuth) TLS() tls.ClientAuthType {
return tls.ClientAuthType(a)
}
100 changes: 100 additions & 0 deletions certificates/auth/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/

package auth

import (
"crypto/tls"
"strings"
)

const (
strict = "strict"
require = "require"
verify = "verify"
request = "request"
none = "none"
)

type ClientAuth tls.ClientAuthType

const (
NoClientCert = ClientAuth(tls.NoClientCert)
RequestClientCert = ClientAuth(tls.RequestClientCert)
RequireAnyClientCert = ClientAuth(tls.RequireAnyClientCert)
VerifyClientCertIfGiven = ClientAuth(tls.VerifyClientCertIfGiven)
RequireAndVerifyClientCert = ClientAuth(tls.RequireAndVerifyClientCert)
)

func List() []ClientAuth {
return []ClientAuth{
NoClientCert,
RequestClientCert,
RequireAnyClientCert,
VerifyClientCertIfGiven,
RequireAndVerifyClientCert,
}
}

func Parse(s string) ClientAuth {
s = strings.ToLower(s)
s = strings.Replace(s, "\"", "", -1)
s = strings.Replace(s, "'", "", -1)
s = strings.TrimSpace(s)

switch {
case strings.Contains(s, strict) || (strings.Contains(s, require) && strings.Contains(s, verify)):
return RequireAndVerifyClientCert
case strings.Contains(s, verify):
return VerifyClientCertIfGiven
case strings.Contains(s, require) && !strings.Contains(s, verify):
return RequireAnyClientCert
case strings.Contains(s, request):
return RequestClientCert
default:
return NoClientCert
}
}

func ParseInt(d int) ClientAuth {
switch tls.ClientAuthType(d) {
case tls.RequireAndVerifyClientCert:
return RequireAndVerifyClientCert
case tls.VerifyClientCertIfGiven:
return VerifyClientCertIfGiven
case tls.RequireAnyClientCert:
return RequireAnyClientCert
case tls.RequestClientCert:
return RequestClientCert
default:
return NoClientCert
}
}

func parseBytes(p []byte) ClientAuth {
return Parse(string(p))
}
63 changes: 63 additions & 0 deletions certificates/auth/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/

package auth

import (
"reflect"

libmap "github.com/mitchellh/mapstructure"
)

func ViperDecoderHook() libmap.DecodeHookFuncType {
return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
var (
z = ClientAuth(0)
t string
k bool
)

// Check if the data type matches the expected one
if from.Kind() != reflect.String {
return data, nil
} else if t, k = data.(string); !k {
return data, nil
}

// Check if the target type matches the expected one
if to != reflect.TypeOf(z) {
return data, nil
}

// Format/decode/parse the data and return the new value
if e := z.unmarshall([]byte(t)); e != nil {
return nil, e
} else {
return z, nil
}
}
}
86 changes: 86 additions & 0 deletions certificates/authClient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* MIT License
*
* Copyright (c) 2020 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/

package certificates

import (
"crypto/x509"

tlsaut "github.com/nabbar/golib/certificates/auth"
tlscas "github.com/nabbar/golib/certificates/ca"
)

func (o *config) SetClientAuth(a tlsaut.ClientAuth) {
o.clientAuth = a
}

func (o *config) GetClientCA() []tlscas.Cert {
var res = make([]tlscas.Cert, 0)

for _, c := range o.clientCA {
res = append(res, c)
}

return res
}

func (o *config) GetClientCAPool() *x509.CertPool {
var res = x509.NewCertPool()

for _, ca := range o.clientCA {
ca.AppendPool(res)
}

return res
}

func (o *config) AddClientCAString(ca string) bool {
if ca != "" {
if c, e := tlscas.Parse(ca); e == nil {
o.clientCA = append(o.clientCA, c)
return true
}
}

return false
}

func (o *config) AddClientCAFile(pemFile string) error {
var fct = func(p []byte) error {
if c, e := tlscas.ParseByte(p); e != nil {
return e
} else {
o.clientCA = append(o.clientCA, c)
return nil
}
}

if e := checkFile(fct, pemFile); e != nil {
return e
} else {
return nil
}
}
Loading

0 comments on commit b78fce5

Please sign in to comment.