Skip to content

Commit

Permalink
v0.0.4-beta
Browse files Browse the repository at this point in the history
  • Loading branch information
yangkenneth committed Oct 18, 2023
1 parent 8af73e8 commit 9ef0711
Show file tree
Hide file tree
Showing 19 changed files with 654 additions and 345 deletions.
5 changes: 3 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.github/
config/*.yml
docs/
examples/
pkg/
Expand All @@ -9,4 +9,5 @@ terraform/

.dockerignore
.git
.gitignore
.gitignore
.github/
2 changes: 1 addition & 1 deletion docs/GETTING_STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Run the `baseca` Container

```sh
docker run -p 9090:9090 -e database_credentials=secret -v ~/.aws/:/home/baseca/.aws/:ro \
-v /path/to/baseca/config:/home/baseca/config ghcr.io/coinbase/baseca:VERSION_SHA
-v /path/to/local/baseca/config:/home/baseca/config ghcr.io/coinbase/baseca:VERSION_SHA
```

### 3b. Compile `baseca` as Executable (Option B)
Expand Down
2 changes: 1 addition & 1 deletion internal/lib/util/validator/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

const (
_dns_regular_expression = `^[a-zA-Z*.]+$`
_dns_regular_expression = `^[a-zA-Z0-9*._-]+$`
)

var valid_domains []string
Expand Down
2 changes: 1 addition & 1 deletion internal/v1/accounts/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func TestCreateServiceAccount(t *testing.T) {
req: &apiv1.CreateServiceAccountRequest{
ServiceAccount: "example",
Environment: "sandbox",
SubjectAlternativeNames: []string{"000.example.com"},
SubjectAlternativeNames: []string{"{}.example.com"},
ExtendedKey: "EndEntityServerAuthCertificate",
CertificateAuthorities: []string{"sandbox_use1"},
SubordinateCa: "infrastructure",
Expand Down
19 changes: 9 additions & 10 deletions internal/v1/middleware/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,15 @@ func (m *Middleware) ServerAuthenticationInterceptor(ctx context.Context, req an
var ok bool

methods := map[string]string{
"/grpc.health.v1.Health/Check": _pass_auth,
"/baseca.v1.Account/LoginUser": _pass_auth,
"/baseca.v1.Account/UpdateUserCredentials": _pass_auth,
"/baseca.v1.Certificate/SignCSR": _service_auth,
"/baseca.v1.Certificate/OperationsSignCSR": _provisioner_auth,
"/baseca.v1.Certificate/QueryCertificateMetadata": _provisioner_auth,
"/baseca.v1.Certificate/GetSignedIntermediateCertificate": _provisioner_auth,
"/baseca.v1.Service/ProvisionServiceAccount": _provisioner_auth,
"/baseca.v1.Service/GetServiceAccountByMetadata": _provisioner_auth,
"/baseca.v1.Service/DeleteProvisionedServiceAccount": _provisioner_auth,
"/grpc.health.v1.Health/Check": _pass_auth,
"/baseca.v1.Account/LoginUser": _pass_auth,
"/baseca.v1.Account/UpdateUserCredentials": _pass_auth,
"/baseca.v1.Certificate/SignCSR": _service_auth,
"/baseca.v1.Certificate/OperationsSignCSR": _provisioner_auth,
"/baseca.v1.Certificate/QueryCertificateMetadata": _provisioner_auth,
"/baseca.v1.Service/ProvisionServiceAccount": _provisioner_auth,
"/baseca.v1.Service/GetServiceAccountByMetadata": _provisioner_auth,
"/baseca.v1.Service/DeleteProvisionedServiceAccount": _provisioner_auth,
}

if auth, ok = methods[info.FullMethod]; !ok {
Expand Down
38 changes: 3 additions & 35 deletions pkg/client/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ package baseca

import (
"context"
"fmt"
"os"

apiv1 "github.com/coinbase/baseca/gen/go/baseca/v1"
"github.com/coinbase/baseca/pkg/types"
"github.com/coinbase/baseca/pkg/util"
)

func (c *client) IssueCertificate(certificateRequest CertificateRequest) (*apiv1.SignedCertificate, error) {
func (c *Client) IssueCertificate(certificateRequest CertificateRequest) (*apiv1.SignedCertificate, error) {
signingRequest, err := GenerateCSR(certificateRequest)
if err != nil {
return nil, err
Expand All @@ -24,7 +23,7 @@ func (c *client) IssueCertificate(certificateRequest CertificateRequest) (*apiv1
return nil, err
}

err = parseCertificateFormat(signedCertificate, types.SignedCertificate{
err = util.ParseCertificateFormat(signedCertificate, types.SignedCertificate{
CertificatePath: certificateRequest.Output.Certificate,
IntermediateCertificateChainPath: certificateRequest.Output.IntermediateCertificateChain,
RootCertificateChainPath: certificateRequest.Output.RootCertificateChain,
Expand All @@ -36,34 +35,3 @@ func (c *client) IssueCertificate(certificateRequest CertificateRequest) (*apiv1

return signedCertificate, nil
}

func parseCertificateFormat(certificate *apiv1.SignedCertificate, parameter types.SignedCertificate) error {
// Leaf Certificate Path
if len(parameter.CertificatePath) != 0 {
certificate := []byte(certificate.Certificate)
if err := os.WriteFile(parameter.CertificatePath, certificate, os.ModePerm); err != nil {
return fmt.Errorf("error writing certificate to [%s]", parameter.CertificatePath)
}
}

// Intermediate Certificate Chain Path
if len(parameter.IntermediateCertificateChainPath) != 0 {
certificate := []byte(certificate.IntermediateCertificateChain)
if err := os.WriteFile(parameter.IntermediateCertificateChainPath, certificate, os.ModePerm); err != nil {
return fmt.Errorf("error writing certificate to [%s]", parameter.IntermediateCertificateChainPath)
}
}

// Root Certificate Chain Path
if len(parameter.RootCertificateChainPath) != 0 {
certificate := []byte(certificate.CertificateChain)
if err := os.WriteFile(parameter.RootCertificateChainPath, certificate, os.ModePerm); err != nil {
return fmt.Errorf("error writing certificate chain to [%s]", parameter.RootCertificateChainPath)
}
}
return nil
}

func (c *client) QueryCertificateMetadata(req *apiv1.QueryCertificateMetadataRequest) (*apiv1.CertificatesParameter, error) {
return c.Certificate.QueryCertificateMetadata(context.Background(), req)
}
147 changes: 58 additions & 89 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package baseca
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"strings"
"sync"
Expand All @@ -17,103 +16,59 @@ import (
"google.golang.org/protobuf/types/known/emptypb"
)

// var Endpoints Environment

var Attestation Provider = Provider{
Local: "NONE",
AWS: "AWS",
}

var Env = Environment{
Local: "Local",
Sandbox: "Sandbox",
Development: "Development",
Staging: "Staging",
PreProduction: "PreProduction",
Production: "Production",
}

type Environment struct {
Local string
Sandbox string
Development string
Staging string
PreProduction string
Production string
}

type Configuration struct {
URL string
Environment string
}

type Provider struct {
Local string
AWS string
}

type Output struct {
CertificateSigningRequest string
Certificate string
IntermediateCertificateChain string
RootCertificateChain string
PrivateKey string
}

type CertificateRequest struct {
CommonName string
SubjectAlternateNames []string
DistinguishedName DistinguishedName
SigningAlgorithm x509.SignatureAlgorithm
PublicKeyAlgorithm x509.PublicKeyAlgorithm
KeySize int
Output Output
}

type DistinguishedName struct {
Country []string
Province []string
Locality []string
Organization []string
OrganizationalUnit []string
}

type Authentication struct {
ClientId string
ClientToken string
}

type client struct {
endpoint string
authentication Authentication
attestation string
Certificate apiv1.CertificateClient
Service apiv1.ServiceClient
}

const (
_client_id_header = "X-BASECA-CLIENT-ID"
_client_token_header = "X-BASECA-CLIENT-TOKEN" // #nosec G101 False Positive
_aws_iid_metadata = "X-BASECA-INSTANCE-METADATA"
_account_auth_header = "AUTHORIZATION"
)

type Client struct {
Endpoint string
Authentication Authentication
Attestation string
Certificate apiv1.CertificateClient
Service apiv1.ServiceClient
}

type AccountClient interface {
LoginUser(ctx context.Context, in *apiv1.LoginUserRequest, opts ...grpc.CallOption) (*apiv1.LoginUserResponse, error)
DeleteUser(ctx context.Context, in *apiv1.UsernameRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
GetUser(ctx context.Context, in *apiv1.UsernameRequest, opts ...grpc.CallOption) (*apiv1.User, error)
ListUsers(ctx context.Context, in *apiv1.QueryParameter, opts ...grpc.CallOption) (*apiv1.Users, error)
CreateUser(ctx context.Context, in *apiv1.CreateUserRequest, opts ...grpc.CallOption) (*apiv1.User, error)
UpdateUserCredentials(ctx context.Context, in *apiv1.UpdateCredentialsRequest, opts ...grpc.CallOption) (*apiv1.User, error)
UpdateUserPermissions(ctx context.Context, in *apiv1.UpdatePermissionsRequest, opts ...grpc.CallOption) (*apiv1.User, error)
}

type CertificateClient interface {
SignCSR(ctx context.Context, in *apiv1.CertificateSigningRequest, opts ...grpc.CallOption) (*apiv1.SignedCertificate, error)
GetCertificate(ctx context.Context, in *apiv1.CertificateSerialNumber, opts ...grpc.CallOption) (*apiv1.CertificateParameter, error)
ListCertificates(ctx context.Context, in *apiv1.ListCertificatesRequest, opts ...grpc.CallOption) (*apiv1.CertificatesParameter, error)
RevokeCertificate(ctx context.Context, in *apiv1.RevokeCertificateRequest, opts ...grpc.CallOption) (*apiv1.RevokeCertificateResponse, error)
OperationsSignCSR(ctx context.Context, in *apiv1.OperationsSignRequest, opts ...grpc.CallOption) (*apiv1.SignedCertificate, error)
QueryCertificateMetadata(ctx context.Context, in *apiv1.QueryCertificateMetadataRequest, opts ...grpc.CallOption) (*apiv1.CertificatesParameter, error)
}

type ServiceClient interface {
CreateServiceAccount(ctx context.Context, in *apiv1.CreateServiceAccountRequest, opts ...grpc.CallOption) (*apiv1.CreateServiceAccountResponse, error)
CreateProvisionerAccount(ctx context.Context, in *apiv1.CreateProvisionerAccountRequest, opts ...grpc.CallOption) (*apiv1.CreateProvisionerAccountResponse, error)
GetProvisionerAccount(ctx context.Context, in *apiv1.AccountId, opts ...grpc.CallOption) (*apiv1.ProvisionerAccount, error)
ListProvisionerAccounts(ctx context.Context, in *apiv1.QueryParameter, opts ...grpc.CallOption) (*apiv1.ProvisionerAccounts, error)
ProvisionServiceAccount(ctx context.Context, in *apiv1.ProvisionServiceAccountRequest, opts ...grpc.CallOption) (*apiv1.ProvisionServiceAccountResponse, error)
GetServiceAccountByMetadata(ctx context.Context, in *apiv1.GetServiceAccountMetadataRequest, opts ...grpc.CallOption) (*apiv1.ServiceAccounts, error)
ListServiceAccounts(ctx context.Context, in *apiv1.QueryParameter, opts ...grpc.CallOption) (*apiv1.ServiceAccounts, error)
GetServiceAccount(ctx context.Context, in *apiv1.AccountId, opts ...grpc.CallOption) (*apiv1.ServiceAccount, error)
GetServiceAccountMetadata(ctx context.Context, in *apiv1.GetServiceAccountMetadataRequest, opts ...grpc.CallOption) (*apiv1.ServiceAccounts, error)
DeleteServiceAccount(ctx context.Context, in *apiv1.AccountId, opts ...grpc.CallOption) (*emptypb.Empty, error)
DeleteProvisionerAccount(ctx context.Context, in *apiv1.AccountId, opts ...grpc.CallOption) (*emptypb.Empty, error)
DeleteProvisionedServiceAccount(ctx context.Context, in *apiv1.AccountId, opts ...grpc.CallOption) (*emptypb.Empty, error)
}

func LoadDefaultConfiguration(configuration Configuration, attestation string, authentication Authentication) (*client, error) {
c := client{
endpoint: configuration.URL,
authentication: authentication,
attestation: attestation,
func LoadDefaultConfiguration(configuration Configuration, attestation string, authentication Authentication) (*Client, error) {
c := Client{
Endpoint: configuration.URL,
Authentication: authentication,
Attestation: attestation,
}

if configuration.Environment == Env.Local {
Expand All @@ -137,14 +92,21 @@ func LoadDefaultConfiguration(configuration Configuration, attestation string, a
}
}

func (c *client) methodInterceptor() grpc.UnaryClientInterceptor {
func (c *Client) methodInterceptor() grpc.UnaryClientInterceptor {
methodOptions := map[string]grpc.UnaryClientInterceptor{
"/baseca.v1.Certificate/SignCSR": c.clientAuthUnaryInterceptor,
"/baseca.v1.Certificate/OperationsSignCSR": c.clientAuthUnaryInterceptor,
"/baseca.v1.Certificate/QueryCertificateMetadata": c.clientAuthUnaryInterceptor,
// Certificate Interface
"/baseca.v1.Certificate/SignCSR": c.clientAuthUnaryInterceptor,
"/baseca.v1.Certificate/OperationsSignCSR": c.clientAuthUnaryInterceptor,
"/baseca.v1.Certificate/QueryCertificateMetadata": c.clientAuthUnaryInterceptor,

// Service Interface
"/baseca.v1.Service/ProvisionServiceAccount": c.clientAuthUnaryInterceptor,
"/baseca.v1.Service/GetServiceAccountByMetadata": c.clientAuthUnaryInterceptor,
"/baseca.v1.Service/DeleteProvisionedServiceAccount": c.clientAuthUnaryInterceptor,

// Account Interface
"/baseca.v1.Account/LoginUser": c.accountAuthUnaryInterceptor,
// TODO: Add Additional RPC Methods
}
return mapMethodInterceptor(methodOptions)
}
Expand Down Expand Up @@ -176,11 +138,11 @@ func returnMethodInterceptor(chainMap sync.Map, method string) (grpc.UnaryClient
return nil, false
}

func (c *client) clientAuthUnaryInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
ctx = metadata.AppendToOutgoingContext(ctx, _client_id_header, c.authentication.ClientId)
ctx = metadata.AppendToOutgoingContext(ctx, _client_token_header, c.authentication.ClientToken)
func (c *Client) clientAuthUnaryInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
ctx = metadata.AppendToOutgoingContext(ctx, _client_id_header, c.Authentication.ClientId)
ctx = metadata.AppendToOutgoingContext(ctx, _client_token_header, c.Authentication.ClientToken)

if c.attestation == Attestation.AWS {
if c.Attestation == Attestation.AWS {
instance_metadata, err := aws_iid.BuildInstanceMetadata()
if err != nil {
return fmt.Errorf("error generating aws_iid node attestation")
Expand All @@ -191,3 +153,10 @@ func (c *client) clientAuthUnaryInterceptor(ctx context.Context, method string,
err := invoker(ctx, method, req, reply, cc, opts...)
return err
}

func (c *Client) accountAuthUnaryInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
ctx = metadata.AppendToOutgoingContext(ctx, _account_auth_header, fmt.Sprintf("Bearer %s", c.Authentication.AuthToken))

err := invoker(ctx, method, req, reply, cc, opts...)
return err
}
Loading

0 comments on commit 9ef0711

Please sign in to comment.