GithubHelp home page GithubHelp logo

go-spiffe's Introduction

go-spiffe (v2)

This library is a convenient Go library for working with SPIFFE.

It leverages the SPIFFE Workload API, providing high level functionality that includes:

  • Establishing mutually authenticated TLS (mTLS) between workloads powered by SPIFFE.
  • Obtaining and validating X509-SVIDs and JWT-SVIDs.
  • Federating trust between trust domains using SPIFFE bundles.
  • Bundle management.

Documentation

See the Go Package documentation.

Quick Start

Prerequisites:

  1. Running SPIRE or another SPIFFE Workload API implementation.
  2. SPIFFE_ENDPOINT_SOCKET environment variable set to address of the Workload API (e.g. unix:///tmp/agent.sock). Alternatively the socket address can be provided programatically.

To create an mTLS server:

listener, err := spiffetls.Listen(ctx, "tcp", "127.0.0.1:8443", tlsconfig.AuthorizeAny())

To dial an mTLS server:

conn, err := spiffetls.Dial(ctx, "tcp", "127.0.0.1:8443", tlsconfig.AuthorizeAny())

The client and server obtain X509-SVIDs and X.509 bundles from the SPIFFE Workload API. The X509-SVIDs are presented by each peer and authenticated against the X.509 bundles. Both sides continue to be updated with X509-SVIDs and X.509 bundles streamed from the Workload API (e.g. secret rotation).

Examples

The examples directory contains rich examples for a variety of circumstances.

go-spiffe's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-spiffe's Issues

Implement jwtbundle.Set type

jwtbundle.Set provides a set of JWT bundles. It also implements the jwtbundle.Source interface. The v2-api branch has scaffolding for all of the methods that need implementing in set.go.

This issue depends on #57.

Introduce Spiffe TLS package

This package should easily generate TLS config geared towards SPIFFE use, i.e. configure certificate validation callbacks etc. We'll use this in spire agent and server

Implement workloadapi.JWTSource

The workloadapi.JWTSource provides JWT materials via the Workload API. It uses the Workload API Client implemented in #68. In particular, it establishes a watch for JWT bundles to maintain fresh up-to-date materials and utilizes the FetchJWTSVID method for sourcing JWT-SVIDs. It implements both the jwtsvid.Source and jwtbundle.Source interfaces.

The v2-api branch has scaffolding for the methods that need implementation in jwtsource.go

This issue depends on #68.

Implement jwtbundle.Bundle type

The jwtbundle.Bundle type contains trusted JWT public keys for a given trust domain. The bundle marshals/unmarshals to/from a JWKS. The v2-api branch has scaffolding for all of the methods that need implementing in bundle.go.

Implement x509bundle.Bundle type

The x509bundle.Bundle type contains trusted X.509 roots for a given trust domain. The bundle marshals/unmarshals from one or more PEM certificate blocks. The v2-api branch has scaffolding for all of the methods that need implementing in bundle.go.

Implement jwtsvid.SVID type and validation

This issue is to implement the jwtsvid.SVID type as outlined in svid.go along with code to parse and validate a JWT-SVID according to the specification.

The SVID type should contain the raw JWT-SVID token as well as denormalized convenience fields for various claims, like the SPIFFE ID (i.e. sub), audience (i.e. aud) and a bucket for the other claims.

There should be two methods:

  1. ParseInsecure - simply parses a token into the SVID type but does not validate. This is mainly useful when the token is received from a trust source (like the workload API)
  2. ParseAndValidate - parses and validates the JWT-SVID token according to the spec and returns the SVID type.

This issue depends on #57 for validation.

Implement x509bundle.Set type

x509bundle.Set provides a set of X.509 bundles. It also implements the x509bundle.Source interface. The v2-api branch has scaffolding for all of the methods that need implementing in set.go.

This issue depends on #55.

v2 bundle types could benefit from a Clone() function

Sometimes it's desirable to manipulate a bundle without disturbing the original. Implementing a Clone() method would make this really simple. Currently, the only way to do it is to either add authorities then remove them, or to pull the authorities out and use them to create a new bundle.

My use case:
I have a bundle I load from disk. I periodically call an upstream authority, and want to return the sum of my loaded bundle and the bundle received from upstream.

Since the bundle received from upstream may change over time, I don't want to hold onto the results across calls. Rather, I want to merge the two and then throw away the result.

X509BundlesResponse type from X.509-SVID profile Workload API does not match SPIFFE specification

The current version of X509BundlesResponse from the X.509-SVID profile of the Workload API is missing a crl field, and the bundles field has an incorrect field number.

Version in go-spiffe v2:

message X509BundlesResponse {
    // x509 certificates, keyed by trust domain URI
    map<string, bytes> bundles = 1;
}

Current version defined in SPIFFE:

// The X509BundlesResponse message carries a set of global CRLs and a map of
// trust bundles the workload should trust.
message X509BundlesResponse {
    // Optional. ASN.1 DER encoded certificate revocation lists.
    repeated bytes crl = 1;


    // Required. CA certificate bundles belonging to trust domains that the
    // workload should trust, keyed by the SPIFFE ID of the trust domain.
    // Bundles are ASN.1 DER encoded.
    map<string, bytes> bundles = 2;
}

Implement x509svid.SVID type

x509svid.SVID represents an X509-SVID with the accompanying private key. Most of the accompanying methods are for marshaling/unmarshaling. It also implements the x509svid.Source interface. The v2-api branch has scaffolding for all of the methods that need implementing in svid.go.

This issue depends on #54.

Add SVID Lint

Add the needed functions to verify that a leaf certificate has all the correct fields set (according to SVID standard)

Implement federation handler

The federation handler provides an HTTP handler that implements the SPIFFE Bundle Endpoint according to the SPIFFE Trust Domain and Bundle specification. The v2-api branch has scaffolding for the implementation in handler.go.

The handler:

  1. Retrieves the bundle from the source on each request (caching bundles is up to the source implementation).
  2. Sets the appropriate Content-Type (i.e. "application/json")
  3. Marshals the bundle to the response

This issue depends on #59, the SPIFFE bundle type implementation.

Implement Federated Bundle Watch

This issue is to implement watching (i.e. polling) for federated bundle updates. It relies on the fetching code implemented for #65 to do periodic refreshing. The v2-api branch has scaffolding for the implementation in watch.go.

This issue depends on #65.

Shouldn't this project be spiffe/go-svid?

The scope of this client library seems to be the SVID rather than the SPIFFE project as a whole (which encompasess many APIs which may have their own Golang client libraries). As such, shouldn't we re-name it go-spiffe?

Implement spiffeid package

The spiffeid package provides types for the SPIFFE ID and Trust Domain. Some of the functionality has been implemented as part of the V2 scaffolding. However, there are two remaining methods: Parse and ParseURI. These two methods are in charge of parsing a SPIFFE ID from a string or URI. They should perform proper validation of the URI, ensuring that it is well formed according to the SPIFFE ID specification.

In addition, the trust domain portion of the SPIFFE ID should be normalized to lower-case to facilitate SPIFFE ID comparison.

Unit-tests for all functionality in the spiffeid package should be introduced as part of implementing this issue.

Implement workloadapi.X509Source

The workloadapi.X509Source provides X.509 materials via the Workload API. It uses the Workload API Client implemented in #68. In particular, it establishes a watch for X.509 Context to maintain fresh up-to-date materials. It implements both the x509svid.Source and x509bundle.Source interfaces.

The v2-api branch has scaffolding for the methods that need implementation in x509source.go.

This issue depends on #68.

Implement spiffebundle.Set type

spiffebundle.Set provides a set of SPIFFE bundles. It also implements the spiffebundle.Source interface. The v2-api branch has scaffolding for all of the methods that need implementing in set.go.

This issue depends on #59.

PEM parsing fails for bundles with trailing newline for v2.0.0-beta.6

Hi,

I noticed behavior that was surprising to me when testing on tag v2.0.0-beta.6. When parsing a PEM file via x509bundle.Parse I receive the following error if there is a trailing newline in the file.

Error:      	Received unexpected error:
       	            	x509bundle: cannot parse certificate: no PEM data found while decoding block
       	            		github.com/spiffe/go-spiffe/v2/bundle/x509bundle.Parse:68
       	            		github.com/spiffe/go-spiffe/v2/bundle/x509bundle_test.TestParse.func1:131
       	            		testing.tRunner:1123
       	Test:       	TestParse/staging_root

I receive no error when removing the newline. My expectation would be to parse without an error, or is this expected behavior?

To reproduce add a trailing newline to go-spiffe/v2/bundle/x509bundle/testdata/certs.pem and run tests.

Implement tlsconfig package

The tlsconfig package contains various methods of creating/updating TLS configuration with the ability to perform SPIFFE authentication over TLS.

There are 3 primitive helper functions:

  • GetCertificate: takes an x509svid.Source and implements the GetCertificate callback for server tls.Config
  • GetClientCertificate: takes an x509svid.Source and implements the GetClientCertificate callback for client tls.Config
  • VerifyPeerCertificate takes an x509bundle.Source and an authorizer and implements the VerifyPeerCertificate callback for both client and server tls.Config.

Along with the primitive helpers, there are a slew of functions that set up a variety of TLS configurations using the above helpers. Most of the implementation can be borrowed from the existing v1 TLS peer implementation.

The v2-api branch has scaffolding for the implementations in config.go.

This issue depends on #55 and #62.

URI Validation in third-party projects

Third-party projects may be hesitant to take dependencies that are SPIFFE-specific. Rather, they're more likely to take one that acts as a generalized URI SAN helper. Perhaps we can have two packages in this repo, one that is generalized and one that is SPIFFE-specific, with the latter consuming the former. Alternatively, we can make this lib generic enough that it doesn't "smell" like SPIFFE.

VerifyPeerCertificate is missing some validation steps

As described in X509-SVID Leaf Validation

When validating an X.509 SVID for authentication purposes, the validator MUST ensure that the CA field in the basic constraints extension is set to false, and that keyCertSign and cRLSign are not set in the key usage extension.

This issue is to track adding of the following validations

  • The certificate is a leaf certificate (I'm not 100% sure this check is occurring)
  • CA field is set to false
  • keyCertSign is not set
  • cRLSign is not set

Introduce SPIFFE validation logic

Introduce validation logic in the SPIFFE helper. It should 1) validate the format of a spiffe certificate, and 2) perform path/chain validation in accordance with x.509 and SVID specs

Implement SPIFFE TLS listening

The spiffetls package is used to facilitate SPIFFE-authenticated TLS connectivity between peers leveraging the Workload API. It essentially ties together the configuration produced by the tlsconfig package with the sources available in the workloadapi package.

This issue is to implement the listening functionality, as scaffolded in listen.go and option.go (the listening related options, that is).

This issue depends on #64 and #69.

Provide single-shot method to get SVIDs

There's many cases where rotation may not be needed (eg, CLI tools, tests, etc). In those cases, a single-shot method to get an x509svid would be convenient.

missing check for 'typ' in token's header

JWTSVID specification states that field 'typ' in header is optional, however, if present, it must be set to either JWT or JOSE. This is not currently being checked in jwtsvid package (not in ParseInsecure nor in ParseAndValidate functions).

generic metric hooks

Over in slack I asked about how we might go about adding the ability to emit metrics out of go-spiffe in a generic way. We've implemented our own wrapper for go-spiffe that wraps the go-spiffe functions like GetClientCertificate that end up in the tls.Config so we can track success and failures from the perspective of each end point.

After chatting about it with the team here at GH we think a implementation similar to the ClientTrace in net/http might be a reasonable solution. The basic idea is that there would be a struct users could configure with functions that would get executed at different points in the go-spiffe codebase. The example they use in the blog post is adding logging when a DNS response is received by the http client.

Some examples of metrics we think might be good points to execute hooks from:

There are likely many others that might make sense as well.

Anyway, I am curious what folks think and wanted to get some consensus before we dig into implementing anything.

Provide a SPIFFE CLI utility in this repository

There is a community need for a generalized SPIFFE CLI utility, with many useful features possible. Among them:

  • Parsing SVIDs and displaying their contents (a-la openssl -text)
  • Validating SVIDS (possibly with or without the workload api present?)
  • Fetching SVIDs from the Workload API
  • Supervising an application, writing SVIDs to disk, signaling as necessary

There are likely additional features that would fit well here (SPIFFE bundle fetching? Munging to type-specific bundles? etc). I would expect this utility to be fetchable/installable via typical go workflow, and would also expect it to fully subsume the functionality currently implemented in https://github.com/spiffe/spiffe-helper

Implement Workload API client

This issue is to implement a primitive wrapper around the Workload API as outlined in client.go and options.go

For the most part, the implementation should more or less be a wrapper around the Workload API gRPC client, converting to/from protobufs and convenience types as necessary. All of the methods on the client are synchronous and straightforward.

Much of the dialing/setup code can be pulled from existing go-spiffe implementations.

The convenience methods in convenience.go should also be implemented as part of this issue. They are all small wrappers that:

  1. create a new client
  2. call the appropriate method
  3. shut down the client.

This issue depends on #55, #56, #57, #58, #62, and #67.

Implement workloadapi.BundleSource

The workloadapi.Bundle provides bundle materials via the Workload API. It uses the Workload API Client implemented in #68. In particular, it establishes a watch for X.509 Context and JWT bundles to maintain fresh up-to-date bundle materials. It implements the spiffebundle.Source, x509bundle.Source, and jwtbundle.Source interfaces.

The v2-api branch has scaffolding for the methods that need implementation in bundlesource.go.

This issue depends on #68.

Usability of tlsconfig.MTLSClientConfig and tlsconfig.MTLSServerConfig

I just spent the better part of half a day stuck with a mysterious inscrutable error from using MTLSServerConfig when I should have used MTLSClientConfig due to copypasta.

That's 100% on me.

I know you guys care a lot about usability, so I thought I'd open a discussion about this being a possible usability problem.

It would be good if either:

  1. There was a tls.Config that was usable for both Server and Client side
    or
  2. The methods were provided for both sides, with the unimplemented side returning a very clear error that is known to bubble up with used with grpc.

Update README to reflect current library state

Lots of things have changed in this library since the README was written. Update the README to reflect the current state, and include some sample code for

  • Starting a basic SPIFFE listener w/ WL API support
  • Using a basic SPIFFE dialer w/ WL API support
  • Anything else that the person picking up this issue thinks might be useful

Implement SPIFFE TLS dialing

The spiffetls package is used to facilitate SPIFFE-authenticated TLS connectivity between peers leveraging the Workload API. It essentially ties together the configuration produced by the tlsconfig package with the sources available in the workloadapi package.

This issue is to implement the dialing functionality, as scaffolded in dial.go and option.go (the dialing related options, that is).

This issue depends on #64 and #69.

Implement Federated Bundle Fetching

This issue is to implement fetching a bundle from the SPIFFE Bundle Endpoint as defined in the [SPIFFE Trust Domain and Bundle] (https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE_Trust_Domain_and_Bundle.md#5-spiffe-bundle-endpoint) specification. The v2-api branch has scaffolding for the implementation in fetch.go.

The code should implement both WebPKI and SPIFFE Authentication (the latter using the tlsconfig package implementation from #64).

This issue depends on #55, #59, and #64.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.