Documentation ¶
Index ¶
- Variables
- func FindConfig(base string, s string) []byte
- func GetSAN(c *x509.Certificate) ([]string, error)
- func IDFromCert(c []*x509.Certificate) string
- func IDFromPublicKeyBytes(m []byte) string
- func JWKThumbprint(pub crypto.PublicKey) (string, error)
- func JwtRawParse(tok string) (head *JWTHead, jwt *JWT, payload []byte, sig []byte, err error)
- func MarshalPrivateKey(priv crypto.PrivateKey) []byte
- func MarshalPublicKey(key crypto.PublicKey) []byte
- func Pub2ID(pub []byte) uint64
- func Pub2VIP(pub []byte) net.IP
- func PublicKey(key crypto.PrivateKey) crypto.PublicKey
- func PublicKeyBase32SHA(key crypto.PublicKey) string
- func RawKeyToPrivateKey(key, pub string) *ecdsa.PrivateKey
- func RawToCertChain(rawCerts [][]byte) ([]*x509.Certificate, error)
- func Register(name string, template func(*Module) error)
- func SPKIFingerprint(key crypto.PublicKey) string
- func Sign(data []byte, p crypto.PrivateKey) []byte
- func SignHash(data []byte, p crypto.PrivateKey) []byte
- func SignerFromKey(key crypto.PrivateKey) crypto.Signer
- func TokenPayload(jwt string) string
- func Verify(data []byte, pub []byte, sig []byte) error
- func VerifyKey(alg string, txt []byte, pk crypto.PublicKey, sig []byte) error
- func VerifySelfSigned(chain []*x509.Certificate) (crypto.PublicKey, error)
- type AudienceOverrideTokenSource
- type Closer
- type ContextDialer
- type Credential
- type Dest
- func (d *Dest) AddCACertPEM(pems []byte) error
- func (d *Dest) AddToken(ma *Mesh, req *http.Request, aut string) error
- func (d *Dest) BackoffReset()
- func (d *Dest) BackoffSleep()
- func (d *Dest) CertPool() *x509.CertPool
- func (d *Dest) DialTLS(a *Mesh, nc net.Conn) (*tls.Conn, error)
- func (d *Dest) GetCACertPEM() []byte
- func (d *Dest) HttpClient() *http.Client
- func (d *Dest) RoundTrip(r *http.Request) (*http.Response, error)
- func (d *Dest) TokenGetter(m *Mesh) TokenSource
- type Duration
- type FileTokenSource
- type Host
- type InitFromEnv
- type JWS
- type JWT
- func (j *JWT) Audience() string
- func (j *JWT) CheckAudience(audExpected []string) bool
- func (j *JWT) Expiry() time.Time
- func (j *JWT) K8SInfo() (string, string)
- func (j *JWT) KSA() (string, string)
- func (jwt *JWT) Sign(privateKey crypto.PrivateKey) string
- func (j *JWT) String() string
- func (j *JWT) VerifySignature(pk crypto.PublicKey) error
- type JWTHead
- type K8SAccountInfo
- type KeyID
- type Mesh
- func (mesh *Mesh) AddModule(m *Module) error
- func (mesh *Mesh) AddRootDER(root []byte) error
- func (mesh *Mesh) AddRoots(rootCertPEM []byte) error
- func (mesh *Mesh) Close(ctx context.Context) error
- func (mesh *Mesh) DialContext(ctx context.Context, network, addr string) (net.Conn, error)
- func (mesh *Mesh) FromEnv(ctx context.Context, base string) error
- func (mesh *Mesh) GenerateTLSConfigServer(allowMeshExternal bool) *tls.Config
- func (mesh *Mesh) Get(base string, out interface{}) error
- func (mesh *Mesh) GetCert() *tls.Certificate
- func (mesh *Mesh) GetCertificate(ctx context.Context, sni string) (*tls.Certificate, error)
- func (mesh *Mesh) GetCerts() map[string]*tls.Certificate
- func (mesh *Mesh) GetDest(addr string) *Dest
- func (mesh *Mesh) GetOrAddDest(ctx context.Context, addr string) (*Dest, error)
- func (mesh *Mesh) GetRaw(base string, suffix string) []byte
- func (mesh *Mesh) GetToken(ctx context.Context, aud string) (string, error)
- func (mesh *Mesh) GetTokenLocal(ctx context.Context, aud string) (string, error)
- func (mesh *Mesh) HandleDisc(w http.ResponseWriter, r *http.Request)
- func (ug *Mesh) HandleUdp(dstAddr net.IP, dstPort uint16, localAddr net.IP, localPort uint16, ...)
- func (mesh *Mesh) Host2ID(host string) string
- func (mesh *Mesh) HttpClient(dest *Dest) *http.Client
- func (mesh *Mesh) HttpTransport(ctx context.Context) *http.Transport
- func (mesh *Mesh) InitCertificates(ctx context.Context, certDir string) error
- func (mesh *Mesh) InitSelfSigned(kty string) *Mesh
- func (mesh *Mesh) InitSelfSignedFromPEMKey(kty string) error
- func (mesh *Mesh) InitSelfSignedKeyRaw(privk crypto.PrivateKey) error
- func (mesh *Mesh) MainEnd()
- func (m *Mesh) Module(name string) *Module
- func (mesh *Mesh) NodeID() []byte
- func (mesh *Mesh) NodeIDUInt(pub []byte) uint64
- func (mesh *Mesh) PrivatePEM() (privPEM []byte)
- func (mesh *Mesh) PubID32() string
- func (mesh *Mesh) SaveCerts(outDir string) error
- func (mesh *Mesh) Self() string
- func (mesh *Mesh) SetCertPEM(privatePEM string, chainPEMCat string) error
- func (mesh *Mesh) Sign(data []byte, sig []byte)
- func (mesh *Mesh) SignCert(priv crypto.PrivateKey, ca crypto.PrivateKey, sans ...string) (tls.Certificate, []byte, []byte)
- func (mesh *Mesh) SignCertDER(pub crypto.PublicKey, caPrivate crypto.PrivateKey, sans ...string) []byte
- func (mesh *Mesh) Spiffee() (*url.URL, string, string, string)
- func (mesh *Mesh) Start(ctx context.Context) error
- func (mesh *Mesh) String() string
- func (mesh *Mesh) TLSClient(ctx context.Context, nc net.Conn, dest *Dest, remotePub32 string) (*tls.Conn, error)
- func (mesh *Mesh) TLSClientConf(dest *Dest, sni string, remotePub32 string) *tls.Config
- func (mesh *Mesh) WorkloadID() string
- type MeshCfg
- type Module
- type MountedTokenSource
- type MultiString
- type PerRPCCredentials
- type PerRPCCredentialsFromTokenSource
- type Router
- type STS
- type STSAuthConfig
- type Starter
- type StaticTokenSource
- type TokenCache
- type TokenResponse
- type TokenSource
- type TokenSourceFunc
- type UDPHandler
- type UdpWriter
Constants ¶
This section is empty.
Variables ¶
var ( // TokenExchangeGrantType is the required value for "grant_type" parameter in a STS request. TokenExchangeGrantType = "urn:ietf:params:oauth:grant-type:token-exchange" // SubjectTokenTypeJWT is the required token type in a STS request. SubjectTokenTypeJWT = "urn:ietf:params:oauth:token-type:jwt" AccessTokenType = "urn:ietf:params:oauth:token-type:access_token" )
var (
Debug = false
)
var ErrUnsupportedKey = errors.New("unknown key type; only RSA and ECDSA are supported")
var (
GCP_SCOPE = "https://www.googleapis.com/auth/cloud-platform"
)
var (
MESH_NETWORK = []byte{0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0x00}
)
Functions ¶
func FindConfig ¶
FindConfig is a simple loader for a config file.
func IDFromCert ¶
func IDFromCert(c []*x509.Certificate) string
func IDFromPublicKeyBytes ¶
func JWKThumbprint ¶
JWKThumbprint creates a JWK thumbprint out of pub as specified in https://tools.ietf.org/html/rfc7638.
func JwtRawParse ¶
JwtRawParse will parse the JWT and extract the elements. WILL NOT VERIFY. From go-oidc/verify.go
func MarshalPrivateKey ¶
func MarshalPrivateKey(priv crypto.PrivateKey) []byte
MarshalPrivateKey returns the PEM encoding of the key
func MarshalPublicKey ¶
Convert a PublicKey to a marshalled format - in the raw format. - 32 byte ED25519 - 65 bytes EC256 ( 0x04 prefix ) - DER RSA key (PKCS1)
Normally the key is available from request or response TLS.PeerCertificate[0]
func Pub2VIP ¶
Convert a public key to a VIP. This is the primary WorkloadID of the nodes. Primary format is the 64-byte EC256 public key.
For RSA, the ASN.1 format of the byte[] is used. For ED, the 32-byte raw encoding.
func PublicKeyBase32SHA ¶
PublicKeyBase32SHA returns a node WorkloadID based on the public key of the node - 52 bytes base32.
func RawKeyToPrivateKey ¶
func RawKeyToPrivateKey(key, pub string) *ecdsa.PrivateKey
func RawToCertChain ¶
func RawToCertChain(rawCerts [][]byte) ([]*x509.Certificate, error)
func Register ¶
Register will register a Module initializer function for a kind of modules, allowing conditional compilation and keeping dependencies separated.
It should be called from small wrappers with conditional compilation tags or from main(). The actual implementation should be in a separate package.
func SPKIFingerprint ¶
Return the SPKI fingerprint of the key https://www.rfc-editor.org/rfc/rfc7469#section-2.4
Can be used with "ignore-certificate-errors-spki-list" in chrome
openssl x509 -pubkey -noout -in <path to PEM cert> | openssl pkey -pubin -outform der \ | openssl dgst -sha256 -binary | openssl base32Enc -base64
sha256/BASE64
func SignerFromKey ¶
func SignerFromKey(key crypto.PrivateKey) crypto.Signer
Return the crypt.Signer interface for the private key.
func TokenPayload ¶
TokenPayload returns the decoded token. Used for logging/debugging token content, without printing the signature.
func Verify ¶
Verify checks the data is signed with the public key pub can be a 64 byte EC256 or 32 byte ED25519
func VerifySelfSigned ¶
func VerifySelfSigned(chain []*x509.Certificate) (crypto.PublicKey, error)
VerifySelfSigned verifies the certificate chain and extract the remote's public key.
Types ¶
type AudienceOverrideTokenSource ¶
type AudienceOverrideTokenSource struct { TokenSource TokenSource Audience string }
type ContextDialer ¶
type ContextDialer interface { // Dial with a context based on tls package - 'once successfully // connected, any expiration of the context will not affect the // connection'. DialContext(ctx context.Context, net, addr string) (net.Conn, error) }
ContextDialer is same with x.net.proxy.ContextDialer Used to create the actual connection to an address using the mesh. The result may have metadata, and be an instance of util.Stream.
A uGate implements this interface, it is the primary interface for creating streams where the caller does not want to pass custom metadata. Based on net and addr and handshake, if destination is capable we will upgrade to BTS and pass metadata. This may also be sent via an egress gateway.
For compatibility, 'net' can be "tcp" and addr a mangled hostname:port Mesh addresses can be identified by the hostname or IP6 address. External addresses will create direct connections if possible, or use egress server.
TODO: also support 'url' scheme
type Credential ¶
type Credential struct { // Identity asserted by this credential - if not set inferred from JWT/cert Principal string // SetCert the cert credential from this directory (or URL) // The 'default' credential will use well-known locations. // All other certs are either explicit or relative to CertDir/NAME CertLocation string // If set, the token source will be used. // Using gRPC interface which returns the full auth string, not only the token // TokenProvider PerRPCCredentials `json:-` // Static token to use. May be a long lived K8S service account secret or other long-lived creds. // Alternative: static token source Token string // TokenSource is the name of the token provier. // If set, a token source with this name is used. The provider must be set in MeshEnv.AuthProviders TokenSource string }
Credential identifies a source of client private info to use for authentication with a destination.
It can be a shared secret (token), private key, etc.
type Dest ¶
type Dest struct { // Addr is the main (VIP or URL) address of the destination. // // For HTTP, Addr is the URL, including any required path prefix, for the destination. // // For TCP, Addr is the TCP address - VIP:port or DNS:port format. tcp:// is assumed. // // For K8S service it should be in the form serviceName.namespace.svc:svcPort // The cluster suffix is assumed to be 'cluster.local' or the custom k8s suffix, // equivalent to cluster.server in kubeconfig. // // This can also be an 'original dst' address for individual endpoints. // // Individual IPs (real or relay like waypoints or egress GW, etc) will be in // the info.addrs field. Addr string `json:"addr,omitempty"` // Proto determines how to talk with the Dest. // Could be 'hbone' (compat with Istio), 'h2c', 'h2', 'ssh', etc. // If not set - Dial will use regular TCP or TLS, depending on the other settings. Proto string `json:"protocol,omitempty"` // VIP is the set of IPs assigned to this destination. // Only set for (frontend) Services. Used when capturing traffic for this service // //VIP []string `json:"alpn,omitempty"` // MeshCluster WorkloadID - the cluster name in kube config, hub, gke - cluster name in XDS // Defaults to Base addr - but it is possible to have multiple clusters for // same address ( ex. different users / token providers). // // Examples: // GKE cluster: gke_PROJECT_LOCATION_NAME // // For mesh nodes: // ID is the (best) primary id known for the node. Format is: // base32(SHA256(EC_256_pub)) - 32 bytes binary, 52 bytes encoded // base32(ED_pub) - same size, for nodes with ED keys. // // For non-mesh nodes, it is a (real) domain name or IP if unknown. // It may include port, or even be a URL - the external destinations may // have different public keys on different ports. // // The node may be a virtual IP ( ex. K8S/Istio service ) or name // of a virtual service. // // If IPs are used, they must be either truncated SHA or included // in the node cert or the control plane must return metadata and // secure low-level network is used (like wireguard) // // Required for secure communication. // // Examples: // - [B32_SHA] // - [B32_SHA].reviews.bookinfo.svc.example.com // - IP6 (based on SHA or 'trusted' IP) // - IP4 ('trusted' IP) // // IPFS: // http://<gateway host>/ipfs/CID/path // http://<cid>.ipfs.<gateway host>/<path> // http://gateway/ipns/IPNDS_ID/path // ipfs://<CID>/<path>, ipns://<peer WorkloadID>/<path>, and dweb://<IPFS address> // // Multiaddr: TLV ID string `json:"id,omitempty"` // Sources of trust for validating the peer destination. // Typically, a certificate - if not set, SYSTEM certificates will be used for non-mesh destinations // and the MESH certificates for destinations using one of the mesh domains. // If not set, the nodes' trust config is used. TrustConfig *authn.TrustConfig `json:"trust,omitempty"` // Expected SANs - if not set, the DNS host in the address is used. // For mesh FQDNs, the namespace will be checked ( second part of the FQDN ) DNSSANs []string `json:"dns_san,omitempty"` //IPSANs []string `json:"ip_san,omitempty"` URLSANs []string `json:"url_san,omitempty"` // SNI to use when making the request. Defaults to hostname in Addr SNI string `json:"sni,omitempty"` ALPN []string `json:"alpn,omitempty"` // Location is set if the cluster has a default location (not global). Location string `json:"location,omitempty"` // If empty, the cluster is using system certs or SPIFFE CAs - as configured in // Mesh. // // Otherwise, it's the configured root certs list, in PEM format. // May include multiple concatenated roots. // // TODO: allow root SHA only. // TODO: move to trust config CACertPEM []byte `json:"ca_cert,omitempty"` // timeout for new network connections to endpoints in cluster ConnectTimeout time.Duration `json:"connect_timeout,omitempty"` TCPKeepAlive time.Duration `json:"tcp_keep_alive,omitempty"` TCPUserTimeout time.Duration `json:"tcp_user_timeout,omitempty"` // Default values for initial window size, initial window, max frame size InitialConnWindowSize int32 `json:"initial_conn_window,omitempty"` InitialWindowSize int32 `json:"initial_window,omitempty"` MaxFrameSize uint32 `json:"max_frame_size,omitempty"` Labels map[string]string `json:"labels,omitempty"` // If set, Bearer tokens will be added. TokenProvider TokenSource `json:-` // If set, a token source with this name is used. The provider must be set in MeshEnv.AuthProviders // If not found, no tokens will be added. If found, errors getting tokens will result // in errors connecting. // In K8S - it will be the well-known token file. TokenSource string `json:"tokens,omitempty"` // WebpushPublicKey is the client's public key. From the getKey("p256dh") or keys.p256dh field. // This is used for Dest that accepts messages encrypted using webpush spec, and may // be used for validating self-signed destinations - this is expected to be the public // key of the destination. // Primary public key of the node. // EC256: 65 bytes, uncompressed format // RSA: DER // ED25519: 32B // Used for sending encryted webpush message // If not known, will be populated after the connection. WebpushPublicKey []byte `json:"pub,omitempty"` // Webpush Auth is a secret shared with the peer, used in sending webpush // messages. WebpushAuth []byte `json:"auth,omitempty"` // If set, the destination is using HTTP protocol - and this is the roundtripper to use. // HttpClient() returns a http client initialized for this destination. // For special cases ( reverse connections in h2r ) it will be a *http2.ClientConn. // RoundTripper http.RoundTripper `json:-` InsecureSkipTLSVerify bool `json:"insecure,omitempty"` Dialer ContextDialer `json:-` // L4Secure is set if the destination can be reached over a secure L4 network (ambient, VPC, IPSec, secure CNI, etc) L4Secure bool `json:"l4secure,omitempty"` // Last packet or registration from the peer. LastSeen time.Time `json:"-"` Backoff time.Duration `json:"-"` Dynamic bool `json:"-"` // Hosts are workload addresses associated with the backend service. // // If empty, the MeshCluster Addr will be used directly - it is expected to be // a FQDN or VIP that is routable - either a service backed by an LB or handled by // ambient or K8S. // // This may be pre-configured or result of discovery (IPs, extra properties). Hosts []*Host `json:"hosts,omitempty"` // contains filtered or unexported fields }
Dest represents a destination and associated security info.
In Istio this is represented as DestinationRule, Envoy - Cluster, K8S Service (the backend side).
This is primarily concerned with the security aspects (auth, transport), and include 'trusted' attributes from K8S configs or JWT/cert.
K8S clusters can be represented as a Dest - rest.Config Host is Addr, CACertPEM ¶
Unlike K8S and Envoy, the port is not required.
This is part of the config - either static or on-demand. The key is the virtual address or IP:port that is either captured or set as backendRef in routes.
func (*Dest) AddCACertPEM ¶
func (*Dest) AddToken ¶
AddToken will add a token to the request, using the 'token source' of the destination.
func (*Dest) BackoffReset ¶
func (d *Dest) BackoffReset()
func (*Dest) BackoffSleep ¶
func (d *Dest) BackoffSleep()
func (*Dest) GetCACertPEM ¶
func (*Dest) HttpClient ¶
HttpClient returns a http client configured to talk with this Dest using a secure connection. - if CACertPEM is set, will be used instead of system
The client is cached in Dest.
func (*Dest) TokenGetter ¶
func (d *Dest) TokenGetter(m *Mesh) TokenSource
type Duration ¶
type Duration struct { // Signed seconds of the span of time. Must be from -315,576,000,000 // to +315,576,000,000 inclusive. Note: these bounds are computed from: // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years Seconds int64 `json:"seconds"` }
From tokenexchangeplugin.go
type Host ¶
type Host struct { // Labels for the workload. Extracted from pod info - possibly TXT records // // 'hbone' can be used for a custom hbone endpoint (default 15008). // Labels map[string]string `json:"labels,omitempty"` // Address is an IP where the host can be reached. // It can be a real IP (in the mesh, direct) or a jump host. // Address string `json:"addr,omitempty"` // FQDN of the host. Used to check host cert. Hostname string }
Host represents the properties of a single workload. By default, clusters resolve the endpoints dynamically, using DNS or EDS or other discovery mechanisms.
type JWS ¶
type JWS struct { Protected string `json:"protected"` Payload string `json:"payload"` Sig string `json:"signature"` }
JWS is the full form, used in ACME protocol with the full header.
type JWT ¶
type JWT struct { //An "aud" (Audience) claim in the token MUST include the Unicode //serialization of the origin (Section 6.1 of [RFC6454]) of the push //resource URL. This binds the token to a specific push service and //ensures that the token is reusable for all push resource URLs that //share the same origin. // In K8S it is an array ! Aud MultiString `json:"aud,omitempty"` //If the application server wishes to provide contact details, it MAY //include a "sub" (Subject) claim in the JWT. The "sub" claim SHOULD //include a contact URI for the application server as either a //"mailto:" (email) [RFC6068] or an "https:" [RFC2818] URI. // // For K8S, system:serviceaccount:NAMESPACE:KSA // Also includes kubernetes.io/serviceaccount/namespace, etc - more verbose and not std Sub string `json:"sub,omitempty"` // Max 24h Exp int64 `json:"exp,omitempty"` IAT int64 `json:"iat,omitempty"` // Issuer - usually a URL, with OIDC keys. // Legacy K8S: kubernetes/serviceaccount Iss string `json:"iss,omitempty"` Email string `json:"email,omitempty"` EmailVerified bool `json:"email_verified,omitempty"` // \"kubernetes.io\":{\"namespace\":\"default\",\"serviceaccount\":{\"name\":\"default\", // \"uid\":\"a47d63f6-29a4-4e95-94a6-35e39ee6d77c\"}}, K8S *K8SAccountInfo `json:"kubernetes.io,omitempty"` Name string `json:"kubernetes.io/serviceaccount/service-account.name,omitempty"` Head *JWTHead `json:"-"` Signed []byte `json:"-"` Payload []byte `json:"-"` Sig []byte `json:"-"` Raw string `json:"-"` }
JWT includes minimal field for a JWT, primarily for extracting iss for the exchange.
This is also used with K8S JWTs, which use multi-string.
func JWTVerifySignature ¶
func JWTVerifySignature(h *JWTHead, b *JWT, txt []byte, sig []byte, pk crypto.PublicKey) (*JWT, error)
JWTVerifySignature will verify "txt" using a public key or other verifiers.
func (*JWT) CheckAudience ¶
checkAudience() returns true if the audiences to check are in the expected audiences. Otherwise, return false.
type JWTHead ¶
type JWTHead struct { Typ string `json:"typ,omitempty"` Alg string `json:"alg,omitempty"` Kid string `json:"kid,omitempty"` JWK json.RawMessage `json:"jwk,omitempty"` Nonce string `json:"nonce,omitempty"` URL string `json:"url,omitempty"` }
First part of the token.
type K8SAccountInfo ¶
type K8SAccountInfo struct {
Namespace string `json:"namespace,omitempty"`
}
type KeyID ¶
type KeyID string
KeyID is the account key identity provided by a CA during registration.
type Mesh ¶
type Mesh struct { *MeshCfg // Node ID - pod ID, CloudRun instanceID, hostname. // // Must be DNS compatible, case insensitive, max 63 ID string `json:"id,omitempty"` // Primary VIP, Created from the PublicKey key VIP6 net.IP // Same as VIP6, but as uint64 VIP64 uint64 // Primary workload ID TLS certificate and private key. Loaded or generated. // Default is to use EC256 certs. The private key can be used to sign JWTs. // The public key and sha can be used as a node identity. Cert *tls.Certificate // Private key. UGate primary key is EC256, in PEM format. // Used for client and server auth for all protocols. // Deprecated - method to get it from Cert. Priv string `json:"priv,omitempty"` // PEM certificate chain CertBytes string `json:"cert,omitempty"` // Explicit certificates (lego), key is hostname from file // CertMap map[string]*tls.Certificate // GetCertificateHook allows plugging in an alternative certificate provider. GetCertificateHook func(host string) (*tls.Certificate, error) // AuthProviders - matching kubeconfig user.authProvider.name // It is expected to return tokens with the given audience - in case of GCP // returns access tokens. If not set the cluster can't be created. // // A number of pre-defined token sources are used: // - gcp - returns GCP access tokens using MDS or default credentials. Used for example by GKE clusters. // - k8s - return K8S WorkloadID tokens with the given audience for default K8S cluster. // - istio-ca - returns K8S tokens with istio-ca audience - used by Citadel and default Istiod // - sts - federated google access tokens associated with GCP identity pools. AuthProviders map[string]TokenSource ClientSessionCache tls.ClientSessionCache Stop chan struct{} // Location is the location of the node - derived from MDS or config. Location string // MuxDialers are used to create an association with a peer and multiplex connections. // HBone, SSH, etc can act as mux dialers. MuxDialers map[string]ContextDialer // Default dialer used to connect to host:port extracted from metadata. // Defaults to net.Dialer, making real connections. // // Can be replaced with a mux or egress dialer or router for // integration. NetDialer ContextDialer // Mux is used for HTTP and gRPC handler exposed externally. // // It is the default handler for "hbone" and "hbonec" protocol handlers. // // The HTTP server on localhost:15000 uses http.DefaultServerMux - // which is also used by pprof and others by default and can't be changed. // It could also be exposed with 'admin' auth wrapper. Mux *http.ServeMux DebugMux *http.ServeMux Routers map[string]Router Handlers map[string]http.Handler // Active modules, by name Listeners map[string]*Module HandlerWrapper func(hf http.Handler, op string) http.Handler RTWrapper func(rt http.RoundTripper) http.RoundTripper // contains filtered or unexported fields }
Mesh represents a workload identity and associated info required for minimal mesh-compatible security. Includes helpers for authentication and basic provisioning.
By default it will attempt to Init a workload cert, and extract info from the cert.
A workload may be associated with multiple service accounts and identity providers, and may have multiple certificates.
func FromEnv ¶
FromEnv will attempt to identify and Init the certificates. This should be called from main() and for normal app use.
New can be used in tests or for fine control over what cert is loaded.
- default GKE/Istio location for workload identity - /var/run/secrets/...FindC - /etc/istio/certs - $HOME/.ssh/id_ecdsa - if it is in standard pem format
ssh-keygen -t ecdsa -b 256 -m PEM -f id_ecdsa
If a cert is found, the identity is extracted from the cert. The platform is expected to refresh the cert.
If a cert is not found, Cert field will be nil, and the app should use one of the methods of getting a cert or call InitSelfSigned.
func New ¶
New initializes the auth systems based on config.
Must call setTLSCertificate to initialize or one of the methods that finds or generates the primary identity.
func (*Mesh) AddRootDER ¶
Add a list of certificates in DER format to the root. The top signer of the workload certificate is added by default.
func (*Mesh) AddRoots ¶
AddRoots will process a PEM file containing multiple concatenated certificates.
func (*Mesh) DialContext ¶
DialContext should connect to the address, using one of the modules and config - falling back to the default dialer.
Normal golang - network is "tcp" and address is host:port - or custom values are allowed.
All forwarding/tunneling methods should call this method to establish outbound connections.
func (*Mesh) GenerateTLSConfigServer ¶
GenerateTLSConfigServer is used to provide the server tls.Config for handshakes.
Will use the workload identity and do basic checks on client certs. It does not require client certs - but asks for them, and if found verifies.
If allowMeshExternal is set, will skip verification for certs with different trust domain.
func (*Mesh) Get ¶
Get finds a config in a store, applies the environ overlay and unmarshalls it. 'base' is the base name for the config - corresponds to GVK in K8S.
func (*Mesh) GetCert ¶
func (mesh *Mesh) GetCert() *tls.Certificate
func (*Mesh) GetCertificate ¶
GetCertificate is typically called during handshake, both server and client. "sni" will be empty for client certificates, and set for server certificates - if not set, workload id is returned.
ctx is the handshake context - may include additional metadata about the operation.
func (*Mesh) GetCerts ¶
func (mesh *Mesh) GetCerts() map[string]*tls.Certificate
Get all known certificates from local files. This is used to support lego certificates and istio.
"istio" is a special name, set if istio certs are found
func (*Mesh) GetOrAddDest ¶
Cluster will get an existing cluster or create a dynamic one. Dynamic clusters can be GC and loaded on-demand.
func (*Mesh) GetRaw ¶
GetRaw will look in all config sources associated with the mesh and attempt to locate the config.
func (*Mesh) GetToken ¶
GetToken is the default token source for the object. Will try: - MDS - AuthProvider["K8S"],"GCP" - locally signed token, using the mesh private key.
TODO: add some audience policy - for example googleapis.com or .mesh.internal.
func (*Mesh) GetTokenLocal ¶
func (*Mesh) HandleDisc ¶
func (mesh *Mesh) HandleDisc(w http.ResponseWriter, r *http.Request)
OIDC discovery on .well-known/openid-configuration
func (*Mesh) HandleUdp ¶
func (ug *Mesh) HandleUdp(dstAddr net.IP, dstPort uint16, localAddr net.IP, localPort uint16, data []byte)
HandleUdp is the common entry point for UDP capture. - tproxy - gvisor/lwIP WIP
func (*Mesh) HttpClient ¶
HttpClient returns a http.Client configured based on the security settings for Dest.
func (*Mesh) InitCertificates ¶
Common setup for cert management. After the 'mesh-env' is loaded (from env, k8s, URL) the next step is to init the workload identity. This must happen before connecting to XDS - since certs is one of the possible auth methods.
The logic is:
- (best case) certificates already provisioned by platform. Detects GKE paths (CAS), old Istio, CertManager style If workload certs are platform-provisioned: extract trust domain, namespace, name, pod id from cert.
- Detect the WORKLOAD_SERVICE_ACCOUNT, trust domain from JWT or mesh-env - Use WORKLOAD_CERT json to Init the config for the CSR, create a CSR - Call CSRSigner. - Save the certificates if running as root or an output dir is set. This will use CAS naming convention.
If envoy + pilot-agent are used, they should be configured to use the cert files. This is done by setting "CA_PROVIDER=GoogleGkeWorkloadCertificate" when starting pilot-agent
func (*Mesh) InitSelfSigned ¶
Will init the Cert, PubID, PublicKey fields - private is in Cert.
func (*Mesh) InitSelfSignedFromPEMKey ¶
InitSelfSignedFromPEMKey will use the private key (EC PEM) and generate a self signed certificate, using the config (name.domain)
func (*Mesh) InitSelfSignedKeyRaw ¶
func (mesh *Mesh) InitSelfSignedKeyRaw(privk crypto.PrivateKey) error
func (*Mesh) NodeIDUInt ¶
func (*Mesh) PrivatePEM ¶
PrivatePEM returns the private key, as PEM
func (*Mesh) SaveCerts ¶
SaveCerts will create certificate files as expected by gRPC and Istio, similar with the auto-created files.
This creates 3 files. NGinx and others also support one file, in the order cert, intermediary, key, and using hostname as the name.
func (*Mesh) Self ¶
Return the self identity. Currently it's using the VIP6 format - may change. This is used in Message 'From' and in ReqContext.
func (*Mesh) SetCertPEM ¶
SetCertPEM explicitly set the certificate and key. The cert will not be rotated - use a dir to reload or call this function with fresh certs before it expires.
func (*Mesh) SignCert ¶
func (mesh *Mesh) SignCert(priv crypto.PrivateKey, ca crypto.PrivateKey, sans ...string) (tls.Certificate, []byte, []byte)
func (*Mesh) SignCertDER ¶
func (*Mesh) TLSClient ¶
func (mesh *Mesh) TLSClient(ctx context.Context, nc net.Conn, dest *Dest, remotePub32 string) (*tls.Conn, error)
GenerateTLSConfigDest returns a custom tls config for a Dest and a context holder. This should be used with a single
func (*Mesh) TLSClientConf ¶
TLSClientConf returns a config for a specific cluster.
sni can override the cluster sni remotePub32 is the cert-baseed identity of a specific endpoint.
func (*Mesh) WorkloadID ¶
type MeshCfg ¶
type MeshCfg struct { // AuthnConfig defines the trust config for the node - the list of signers that are trusted for specific // issuers and domains, audiences, etc. // // Based on Istio jwtRules, but generalized to all signer types. // // Authz is separated - this only defines who do we trust (and policies on what we trust it for) // // Destinations and listeners may have their own AuthnConfig - this is the default. authn.AuthnConfig `json:",inline"` // Will attempt to Init/reload certificates and configs from this directory. // // If empty, default platform locations will be used. "-" will disable loading configs. // TODO: URLs, k8s, etc. ConfigLocation string `json:"configLocation,omitempty"` // Trusted roots, in DER format. // Deprecated - AuthnConfig RootCertificates [][]byte `json:"roots,omitempty"` // Domain is extracted from the cert or set by user, used to verify // peer certificates. If not set, will be populated when cert is loaded. // Should be a real domain with OIDC keys or platform specific. // NOT cluster.local Domain string `json:"domain,omitempty"` DomainAliases []string `json:"domainAliases,omitempty"` // Namespace and Name are extracted from the certificate or set by user. // Namespace is used to verify peer certificates Namespace string `json:"namespace,omitempty"` // Name of the service account. Can be an email or spiffee or just the naked name. Name string `json:"name,omitempty"` // Deprecated - MDS ProjectID string `json:"project_id,omitempty"` GSA string `json:"gsa,omitempty"` // Authz: Additional namespaces to allow access from. If no authz rule is set, 'same namespace' // and 'istio-system' are allowed. AllowedNamespaces []string `json:"allow_namespaces,omitempty"` // DER public key PublicKey []byte `json:"pub,omitempty"` // EC256 key, in base64 format. Used for self-signed identity and webpush. // Deprecated EC256Key string `json:"-"` EC256Pub string `json:"-"` // MeshAddr is a URL or string representing the primary (bootstrap) address // for the mesh config - can be a K8S cluster, XDS server, file. MeshAddr string `json:"meshAddr,omitempty"` // Dst contains pre-configured or discovered properties for destination services. // When running in K8S, "KUBERNETES" is set with the in-cluster config. // A .kube/config file can be converted to dst if a subset of auth is used. // // K8S Services, SSH hosts, etc are also represented as Dst. Dst map[string]*Dest `json:"dst,omitempty"` // Modules contains the enabled modules for this mesh. // The value is a list of key/pair settings. // The name of the module will be used to locate the component. Modules []*Module `json:"modules,omitempty"` // Additional defaults for outgoing connections. // Probably belong to Dest. ConnectTimeout Duration `json:"connect_timeout,omitempty"` TCPUserTimeout time.Duration // Timeout used for TLS or SSH handshakes. If not set, 3 seconds is used. HandsahakeTimeout time.Duration Env map[string]string }
MeshCfg is used to configure the mesh basic settings related to security.
It includes definition of listeners and cluters (dst) - with associated keys/certs. This package does not provide any protocol or listening.
type Module ¶
type Module struct { Name string `json:"name"` // A module may use an address to initialize - should be host:port (go style), // or a URL. Semantic specific to the module - can be the default listen address // or an address to connect to. This is a common setting so keeping it top level. Address string `json:"address,omitempty"` // TODO: rename to 'remoteAddress' or 'dest' - use to indicate an address to use as client ForwardTo string `json:"forwardTo,omitempty"` // Internal state. NetListener net.Listener `json:"-"` // Mux is the main server mux, for L7 modules. Mux http.ServeMux `json:"-"` // Env variables - not meant to be used as a real config, but better than direct use of os.Getenv // Getenv may check os env variables too. Env map[string]string `json:"env,omitempty"` Mesh *Mesh `json:"-"` // The module native interface. Module interface{} `json:"-"` }
Module is a component providing a specific functionality, similar to a .so file in traditional servers. In many cases it provides a listener or dialer or some other service.
Usually a protocol implementation, callbacks, etc. This allows a 'modular monolith' approach and avoids deps. The Module is an instance of a module with a specific name and set of key/value settings.
TODO: why not support .so files and dynamic load ?
type MountedTokenSource ¶
type MountedTokenSource struct {
Base string
}
type MultiString ¶
type MultiString []string
func (*MultiString) MarshalJSON ¶
func (ms *MultiString) MarshalJSON() ([]byte, error)
func (*MultiString) UnmarshalJSON ¶
func (ms *MultiString) UnmarshalJSON(data []byte) error
type PerRPCCredentials ¶
type PerRPCCredentials interface { // GetRequestMetadata gets the current request metadata, refreshing // tokens if required. This should be called by the transport layer on // each request, and the data should be populated in headers or other // context. If a status code is returned, it will be used as the status // for the RPC. uri is the URI of the entry point for the request. // When supported by the underlying implementation, ctx can be used for // timeout and cancellation. Additionally, RequestInfo data will be // available via ctx to this call. // TODO(zhaoq): Define the set of the qualified keys instead of leaving // it as an arbitrary string. GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) // RequireTransportSecurity indicates whether the credentials requires // transport security. RequireTransportSecurity() bool }
PerRPCCredentials defines the common interface for the credentials which need to attach security information to every RPC (e.g., oauth2). This is the interface used by gRPC - should be implemented by all TokenSource to allow use with gRPC.
type PerRPCCredentialsFromTokenSource ¶
type PerRPCCredentialsFromTokenSource struct {
TokenSource
}
func (*PerRPCCredentialsFromTokenSource) GetRequestMetadata ¶
func (*PerRPCCredentialsFromTokenSource) RequireTransportSecurity ¶
func (s *PerRPCCredentialsFromTokenSource) RequireTransportSecurity() bool
type STS ¶
type STS struct {
// contains filtered or unexported fields
}
STS provides token exchanges (RFC8694).
The secure token is the K8S or other IDP token with a special audience, the result is a 'federated access token' for GCP or a regular JWT for other token exchange servers.
For GKE and GCP - the special values will be used.
See https://cloud.google.com/iam/docs/reference/sts/rest https://www.rfc-editor.org/rfc/rfc6749 - basic oauth2 https://www.rfc-editor.org/rfc/rfc8693.html https://www.ietf.org/archive/id/draft-richer-oauth-json-request-00.html
func NewFederatedTokenSource ¶
func NewFederatedTokenSource(kr *STSAuthConfig) *STS
NewFederatedTokenSource returns federated tokens - google access tokens associated with the federated (k8s) identity. Can be used in some but not all APIs - in particular MeshCA requires this token.
https://cloud.google.com/iam/docs/reference/sts/rest/v1/TopLevel/token
If GSA is set, will also delegate to a Google account.
func (*STS) TokenGSA ¶
Exchange a federated token equivalent with the k8s JWT with the ASM p4SA. TODO: can be used with any GSA, if the permission to call generateAccessToken is granted. This is a good way to get access tokens for a GSA using the KSA, similar with TokenRequest in the other direction.
May return an WorkloadID token with aud or access token.
constructFederatedTokenRequest returns an HTTP request for access token.
Example of an access token request:
POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service-<GCP project number>@gcp-sa-meshdataplane.iam.gserviceaccount.com:generateAccessToken Content-Type: application/json Authorization: Bearer <federated token>
{ "Delegates": [], "Scope": [ https://www.googleapis.com/auth/cloud-platform ], }
This requires permission to impersonate:
gcloud iam service-accounts add-iam-policy-binding \ GSA_NAME@GSA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/iam.workloadIdentityUser \ --member="serviceAccount:WORKLOAD_IDENTITY_POOL[K8S_NAMESPACE/KSA_NAME]"
This can also be used with user access tokens, if user has
roles/iam.serviceAccountTokenCreator (for iam.serviceAccounts.getOpenIdToken)
The p4sa is auto-setup for all authenticated users in ASM.
type STSAuthConfig ¶
type STSAuthConfig struct { // TokenSource returns 'source' tokens - with special audience that allows // them to be exchanged. // // For GKE - the audience should be PROJECT.svc.id.goog. // Can be a file source when running in K8S, if the token is mounted. TokenSource TokenSource // AudienceSource to use when getting tokens from TokenSource. // On GKE: fleet_project_name.svc.id.goog // // Will be used in the identitynamespace param as well as 'audience' in TokenRequest calls. // If missing - can be extracted from the token. AudienceSource string // GKE Dest address. // https://container.googleapis.com/v1/projects/%s/locations/%s/clusters/%s // It is also the iss field in the token. // // By default, it will be populated the first time a token is requested. ClusterAddress string // Endpoint for the STS exchange - takes a IDP JWT and gets back a // federated access token. // // If empty, defaults to google: "https://sts.googleapis.com/v1/token" STSEndpoint string // Scope to use in the STS exchange. // Defaults to google: "https://www.googleapis.com/auth/cloud-platform" Scope string // GSA is a Google service account that allows the federated identity to impersonate it ( use ). // If not set, the STS will only return access tokens in GCP. // If set, the federated token will be exchanged with an ID or access token. // // The gsa must grant the KSA (kubernetes service account) or source account // permission to act as the GSA. // // In ASM, a pre-setup account with permissions to stackdriver and control plane is // "service-" + projectNumber + "@gcp-sa-meshdataplane.iam.gserviceaccount.com" // // REQUIRES for regular service account: // // gcloud iam service-accounts add-iam-policy-binding \ // --role roles/iam.workloadIdentityUser \ // --member "serviceAccount:${CONFIG_PROJECT_ID}.svc.id.goog[${WORKLOAD_NAMESPACE}/default]" \ // k8s-${WORKLOAD_NAMESPACE}@${PROJECT_ID}.iam.gserviceaccount.com GSA string // If true, the TokenSource returns access tokens directly. // If false, the TokenSource is K8S-based and used to returns K8S JWTs with // AudienceSource, further exchanged to federated access tokens, and if GSA is // set to service JWT or access tokens. // // Federated tokens also require cluster info. GCPDelegate bool }
STSAuthConfig contains the settings for getting tokens using K8S or other federated tokens. Common usage is with a GKE cluster, with either mounted or JWT tokens from TokenRequest.
The mounted tokens MUST use PROJECT_ID.svc.id.goog as audience.
type StaticTokenSource ¶
type StaticTokenSource struct {
Token string
}
type TokenCache ¶
type TokenCache struct { TokenSource TokenSource // DefaultExpiration of tokens - 45 min if not set. // TokenSource doesn't deal with expiration, in almost all cases 1h retry is ok. DefaultExpiration time.Duration // contains filtered or unexported fields }
type TokenResponse ¶
type TokenResponse struct { // REQUIRED. The security token issued by the authorization server // in response to the token exchange request. AccessToken string `json:"access_token"` // REQUIRED. An identifier, representation of the issued security token. IssuedTokenType string `json:"issued_token_type"` // REQUIRED. A case-insensitive value specifying the method of using the access // token issued. It provides the client with information about how to utilize the // access token to access protected resources. TokenType string `json:"token_type"` // RECOMMENDED. The validity lifetime, in seconds, of the token issued by the // authorization server. ExpiresIn int64 `json:"expires_in"` // OPTIONAL, if the Scope of the issued security token is identical to the // Scope requested by the client; otherwise, REQUIRED. Scope string `json:"scope"` // OPTIONAL. A refresh token will typically not be issued when the exchange is // of one temporary credential (the subject_token) for a different temporary // credential (the issued token) for use in some other context. RefreshToken string `json:"refresh_token"` }
TokenResponse stores all attributes sent as JSON in a successful STS response. These attributes are defined in RFC8693 2.2.1 Also RFC6749 5.1 and https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16#section-2.2.1 Also used by the MDS.
type TokenSource ¶
type TokenSource interface { // GetToken for a given audience. GetToken(context.Context, string) (string, error) }
TokenSource is a common interface for anything returning Bearer or other kind of tokens.
type TokenSourceFunc ¶
type UDPHandler ¶
type UDPHandler interface {
HandleUdp(dstAddr net.IP, dstPort uint16, localAddr net.IP, localPort uint16, data []byte)
}
UDPHandler is used to abstract the handling of incoming UDP packets on a UDP listener or TUN.
type UdpWriter ¶
type UdpWriter interface {
WriteTo(data []byte, dstAddr *net.UDPAddr, srcAddr *net.UDPAddr) (int, error)
}
UdpWriter is the interface implemented by the TunTransport, to send packets back to the virtual interface. TUN or TProxy raw support this. Required for 'transparent' capture of UDP - otherwise use STUN/TURN/etc. A UDP NAT does not need this interface.