Documentation
¶
Overview ¶
Package webpush provides helper functions for sending encrpyted payloads using the Web Push protocol.
Sending a message:
import ( "strings" "github.com/googlechrome/webpush/webpush" ) func main() { // The values that make up the Subscription struct come from the browser sub := &webpush.Subscription{endpoint, key, auth} webpush.Send(nil, sub, "Yay! Web Push!", nil) }
You can turn a JSON string representation of a PushSubscription object you collected from the browser into a Subscription struct with a helper function.
var exampleJSON = []byte(`{"endpoint": "...", "keys": {"p256dh": "...", "auth": "..."}}`) sub, err := SubscriptionFromJSON(exampleJSON)
If the push service requires an authentication header (notably Google Cloud Messaging, used by Chrome) then you can add that as a fourth parameter:
if strings.Contains(sub.Endpoint, "https://android.googleapis.com/gcm/send/") { webpush.Send(nil, sub, "A message for Chrome", myGCMKey) }
Index ¶
- Constants
- Variables
- func ContextWithAuth(ctx context.Context, h2c *ReqContext) context.Context
- func GetMDSIDToken(ctx context.Context, aud string) (string, error)
- func GetPeerCertBytes(r *http.Request) []byte
- func GetResponseCertBytes(r *http.Response) []byte
- func GetSAN(c *x509.Certificate) ([]string, error)
- func GetToken(aud string) string
- func IDFromCert(c []*x509.Certificate) string
- func IDFromPublicKey(key crypto.PublicKey) string
- func IDFromPublicKeyBytes(m []byte) string
- func JwtRawParse(tok string) (*JWTHead, *JWT, []byte, []byte, error)
- func MDS(w http.ResponseWriter, r *http.Request)
- func MarshalPrivateKey(key crypto.PrivateKey) []byte
- func MarshalPublicKey(key crypto.PublicKey) []byte
- func MetadataGet(ctx context.Context, path string) (string, error)
- func ParseAuthorization(auth string) (string, string, map[string]string)
- func ParseXFCC(val string) map[string]string
- func Pub2ID(pub []byte) uint64
- func Pub2VIP(pub []byte) net.IP
- func PubKeyFromCertChain(chain []*x509.Certificate) (crypto.PublicKey, error)
- func PublicKeyBytesRaw(key crypto.PublicKey) []byte
- func RawToCertChain(rawCerts [][]byte) ([]*x509.Certificate, error)
- func TokenPayload(jwt string) string
- func Verify(data []byte, pub []byte, sig []byte) error
- type Auth
- func (auth *Auth) GenerateTLSConfigClient() *tls.Config
- func (auth *Auth) GetCerts() map[string]*tls.Certificate
- func (a *Auth) HandleDisc(w http.ResponseWriter, r *http.Request)
- func (a *Auth) HandleJWK(w http.ResponseWriter, r *http.Request)
- func (a *Auth) HandleSTS(w http.ResponseWriter, req *http.Request)
- func (auth *Auth) Host2ID(host string) string
- func (a *Auth) LoadManaged()
- func (a *Auth) NewContextUA(auth []byte) *EncryptionContext
- func (auth *Auth) NodeID() []byte
- func (auth *Auth) NodeIDUInt(pub []byte) uint64
- func (auth *Auth) SaveKubeconfig(name string, keyPEM []byte, certPEM []byte)
- func (a *Auth) Self() string
- func (a *Auth) SetTLSCertificate(cert *tls.Certificate) error
- func (v *Auth) SetVapid(publicKey64, privateKey64 string)
- func (auth *Auth) Sign(data []byte, sig []byte)
- func (auth *Auth) SignCSR(csrBytes []byte, org string, sans ...string) ([]byte, error)
- func (auth *Auth) SignCert(priv crypto.PrivateKey, ca crypto.PrivateKey, sans ...string) (tls.Certificate, []byte, []byte)
- func (a *Auth) Spiffee() (*url.URL, string, string, string)
- func (auth *Auth) VAPIDToken(aud string) string
- type AuthConfig
- type ConfStore
- type Context
- type Duration
- type EncryptionContext
- type JWT
- type JWTHead
- type JWTRule
- type K8SAccountInfo
- type KubeCluster
- type KubeConfig
- type KubeNamedCluster
- type KubeNamedContext
- type KubeNamedUser
- type KubeUser
- type MultiString
- type RemoteID
- type ReqContext
- type STS
- func (s *STS) ExternalSA() string
- func (s *STS) GetRequestMetadata(ctx context.Context, aud ...string) (map[string]string, error)
- func (s *STS) GetToken(ctx context.Context, aud string) (string, error)
- func (s *STS) RequireTransportSecurity() bool
- func (s *STS) ServeStsRequests(w http.ResponseWriter, req *http.Request)
- func (s *STS) TokenAccess(ctx context.Context, federatedToken string, audience string) (string, error)
- func (s *STS) TokenFederated(ctx context.Context, k8sSAjwt string) (string, error)
- type StsErrorResponse
- type StsRequestParameters
- type StsResponseParameters
- type Subscription
- type TokenCache
- type TokenSource
- type UserAuthProvider
Constants ¶
const ( WorkloadCertDir = "/var/run/secrets/workload-spiffe-credentials" // This is derived from CA certs plus all TrustAnchors. // In GKE, it is expected that Citadel roots will be configure using TrustConfig - so they are visible // to all workloads including TD proxyless GRPC. // // Outside of GKE, this is loaded from the mesh.env - the mesh gate is responsible to keep it up to date. WorkloadRootCAs = "ca_certificates.pem" )
const UseMDSFullToken = true
Variables ¶
var ( // SecureTokenEndpoint is the Endpoint the STS client calls to. SecureTokenEndpoint = "https://sts.googleapis.com/v1/token" Scope = "https://www.googleapis.com/auth/cloud-platform" // Server side // TokenPath is url path for handling STS requests. TokenPath = "/token" // StsStatusPath is the path for dumping STS status. StsStatusPath = "/stsStatus" // URLEncodedForm is the encoding type specified in a STS request. URLEncodedForm = "application/x-www-form-urlencoded" // TokenExchangeGrantType is the required value for "grant_type" parameter in a STS request. TokenExchangeGrantType = "urn:ietf:params:oauth:grant-type:token-exchange" // SubjectTokenType is the required token type in a STS request. SubjectTokenType = "urn:ietf:params:oauth:token-type:jwt" Debug = false )
From nodeagent/plugin/providers/google/stsclient In Istio, the code is used if "GoogleCA" is set as CA_PROVIDER or CA_ADDR has the right prefix
var (
MESH_NETWORK = []byte{0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0x00}
)
Functions ¶
func ContextWithAuth ¶
func ContextWithAuth(ctx context.Context, h2c *ReqContext) context.Context
func GetMDSIDToken ¶
Get an ID token from platform (GCP, etc)
curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=[AUDIENCE]" \ -H "Metadata-Flavor: Google"
May fail and need retry
func GetResponseCertBytes ¶
func IDFromCert ¶
func IDFromCert(c []*x509.Certificate) string
func IDFromPublicKey ¶
IDFromPublicKey returns a node ID based on the public key of the node - 52 bytes base32.
func IDFromPublicKeyBytes ¶
func MDS ¶
func MDS(w http.ResponseWriter, r *http.Request)
MDS emulates the GCP metadata server. MDS address is 169.254.169.254:80 - can be intercepted with iptables, or set using GCE_METADATA_HOST
gRPC library will use it if: - the env variable is set - a probe to the IP and URL / returns the proper flavor. - DNS resolves metadata.google.internal to the IP
func MarshalPrivateKey ¶
func MarshalPrivateKey(key crypto.PrivateKey) []byte
func MarshalPublicKey ¶
func MetadataGet ¶
GetMDS returns MDS info on google: instance/hostname - node name.c.PROJECT.internal instance/attributes/cluster-name, cluster-location project/project-id, numeric-project-id instance/service-accounts/ - default, PROJECTID.svc.id.goog instance/service-accounts/default/identity - requires the iam.gke.io/gcp-service-account=gsa@project annotation and IAM instance/service-accounts/default/token - access token for the KSA
func ParseAuthorization ¶
ParseAuthorization splits the Authorization header, returning the scheme and parameters. Used with the "scheme k=v,k=v" format.
func ParseXFCC ¶
ParseXFCC is a minimal (and probably buggy) parser for XFCC envoy header. It does not deal with quoted strings including special chars (,;=). Istio certs are safe.
func Pub2VIP ¶
Convert a public key to a VIP. This is the primary ID 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 PubKeyFromCertChain ¶
func PubKeyFromCertChain(chain []*x509.Certificate) (crypto.PublicKey, error)
PubKeyFromCertChain verifies the certificate chain and extract the remote's public key.
func PublicKeyBytesRaw ¶
Convert a PublicKey to a marshalled format - in the raw format. - 32 byte ED25519 - 65 bytes EC256 ( 0x04 prefix ) - DER RSA key (PKCS1)
func RawToCertChain ¶
func RawToCertChain(rawCerts [][]byte) ([]*x509.Certificate, error)
func TokenPayload ¶
TokenPayload returns the decoded token. Used for logging/debugging token content, without printing the signature.
Types ¶
type Auth ¶
type Auth struct { // MeshAuth is minimal, simplified version of auth based only on platform certs. meshauth.MeshAuth // Public part of the Auth info //ugate.DMNode PublicKey []byte `json:"pub,omitempty"` ID string `json:"id,omitempty"` // Primary VIP, Created from the PublicKey key, will be included in the self-signed cert. VIP6 net.IP // Same as VIP6, but as uint64 VIP64 uint64 // Blob store - for loading/saving certs and keys. If nil, all is just in memory. Config ConfStore // Moved to base // User name, based on service account or uid. Name string // Private key to use in both server and client authentication. // ED22519: 32B // EC256: DER // RSA: DER Priv []byte // Explicit certificates (lego), key is hostname from file // CertMap map[string]*tls.Certificate // contains filtered or unexported fields }
Support for ID and authn using certificates and workload identity.
Private key, certificates and associated helpers. An IPv6 address is derived from the public key.
Auth represents a workload identity and associated info. It can load existing certificates from the well known location, and can save certificates to the well known locations.
When loading existing certificate it can extract namespace/trustdomain/sa.
func NewAuth ¶
NewAuth initializes the auth using environment, local files or the config store.
If no private key is found, generate an EC256 key.
func NewMeshAuth ¶
func NewMeshAuth() *Auth
func (*Auth) GenerateTLSConfigClient ¶
Generate a config to be used in a HTTP client, using the primary identity and cert.
func (*Auth) GetCerts ¶
func (auth *Auth) 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 (*Auth) HandleDisc ¶
func (a *Auth) HandleDisc(w http.ResponseWriter, r *http.Request)
OIDC discovery on .well-known/openid-configuration
func (*Auth) HandleSTS ¶
func (a *Auth) HandleSTS(w http.ResponseWriter, req *http.Request)
RFC8693 - token exchange ex. for GCP: https://cloud.google.com/iam/docs/reference/sts/rest/v1beta/TopLevel/token https://cloud.google.com/iam/docs/reference/credentials/rest
func (*Auth) LoadManaged ¶
func (a *Auth) LoadManaged()
func (*Auth) NewContextUA ¶
func (a *Auth) NewContextUA(auth []byte) *EncryptionContext
func (*Auth) NodeIDUInt ¶
func (*Auth) SaveKubeconfig ¶
SaveKubeconfig will save the current keys and config as a kube config file.
func (*Auth) Self ¶
Return the self identity. Currently it's using the VIP6 format - may change. This is used in Message 'From' and in ReqContext.
func (*Auth) SetTLSCertificate ¶
func (a *Auth) SetTLSCertificate(cert *tls.Certificate) error
import (
"context" "crypto/tls" "crypto/x509" "encoding/pem" "errors" "fmt" "io/ioutil" "log" "net/url" "os" "path/filepath" "strings" "time"
)
// This handles the ideal mesh case - platform managed workload certificates. // Also handles pilot-agent managing the certs.
// MeshAuth represents a workload identity and associated info required for minimal Mesh-compatible security.
type MeshAuth struct { // Will attempt to load certificates from this directory, defaults to // "./var/run/secrets/istio.io/" CertDir string // Current certificate, after calling GetCertificate("") Cert *tls.Certificate // MeshTLSConfig is a tls.Config that requires mTLS with a spiffee identity, // using the configured roots, trustdomains. // // By default only same namespace or istio-system are allowed - can be changed by // setting AllowedNamespaces. A "*" will allow all. MeshTLSConfig *tls.Config // TrustDomain is extracted from the cert or set by user, used to verify // peer certificates. TrustDomain string // Namespace and SA are extracted from the certificate or set by user. // Namespace is used to verify peer certificates Namespace string SA string // Additional namespaces to allow access from. By default 'same namespace' and 'istio-system' are allowed. AllowedNamespaces []string // Trusted roots // TODO: copy Istiod multiple trust domains code. This will be a map[trustDomain]roots and a // list of TrustDomains. XDS will return the info via ProxyConfig. // This can also be done by krun - loading a config map with same info. TrustedCertPool *x509.CertPool // GetCertificateHook allows plugging in an alternative certificate provider. By default files are used. GetCertificateHook func(host string) (*tls.Certificate, error) }
func (a *MeshAuth) GenerateTLSConfigServer() *tls.Config { return a.MeshTLSConfig }
func (a *MeshAuth) GenerateTLSConfigClient(name string) *tls.Config { return a.MeshTLSConfig.Clone() }
// NewMeshAuth creates the auth object. No keys are set. // // Private key, roots, config must be initialized and loaded. Use NewAuth(...) for automated loading // from environment/filesystem.
func NewMeshAuth() *Auth { a := &Auth{ TrustedCertPool: x509.NewCertPool(), } return a }
// mesh certificates - new style const (
WorkloadCertDir = "/var/run/secrets/workload-spiffe-credentials" // Different from typical Istio and CertManager key.pem - we can check both privateKey = "private_key.pem" // Also different, we'll check all. CertManager uses cert.pem cert = "certificates.pem" // This is derived from CA certs plus all TrustAnchors. // In GKE, it is expected that Citadel roots will be configure using TrustConfig - so they are visible // to all workloads including TD proxyless GRPC. // // Outside of GKE, this is loaded from the mesh.env - the mesh gate is responsible to keep it up to date. WorkloadRootCAs = "ca_certificates.pem"
)
// CSRSigner is the provider interface for signing certs, defined in Istio. // CSR is generated by Auth.
type CSRSigner interface { CSRSign(ctx context.Context, csrPEM []byte, certValidTTLInSec int64) ([]string, error) GetRootCertBundle() ([]string, error) }
// Will load the credentials and create an Auth object. // // This uses pilot-agent or some other platform tool creating ./var/run/secrets/istio.io/{key,cert-chain}.pem // // // TODO: ./etc/certs support: krun should copy the files, for consistency (simper code for frameworks). // TODO: periodic reload
func (a *Auth) SetKeysDir(dir string) error { a.CertDir = dir err := a.waitAndInitFromDir() if err != nil { return err } return nil }
func (a *Auth) SetKeysPEM(privatePEM []byte, chainPEM []string) error { chainPEMCat := strings.Join(chainPEM, "\n") tlsCert, err := tls.X509KeyPair([]byte(chainPEMCat), privatePEM) if err != nil { return err } if tlsCert.Certificate == nil || len(tlsCert.Certificate) == 0 { return errors.New("missing certificate") } return a.SetTLSCertificate(&tlsCert) }
func (*Auth) SetVapid ¶
SetVapid sets a new Vapid generator from EC256 public and private keys, in base64 uncompressed format.
func (*Auth) SignCert ¶
func (auth *Auth) SignCert(priv crypto.PrivateKey, ca crypto.PrivateKey, sans ...string) (tls.Certificate, []byte, []byte)
func (*Auth) Spiffee ¶
// 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 (a *Auth) GetCertificate(ctx context.Context, sni string) (*tls.Certificate, error) { // TODO: if host != "", allow returning DNS certs for the host. // Default (and currently only impl) is to return the spiffe cert // May refresh. c, ok := a.CertMap[sni] if ok { return c, nil } // Have cert, not expired if a.Cert != nil { if !a.leaf().NotAfter.Before(time.Now()) { return a.Cert, nil } } if a.CertDir != "" { c, err := a.loadCertFromDir(a.CertDir) if err == nil { if !c.Leaf.NotAfter.Before(time.Now()) { a.Cert = c } } else { log.Println("Cert from dir failed", err) } } if a.GetCertificateHook != nil { c, err := a.GetCertificateHook(sni) if err != nil { return nil, err } a.Cert = c } return a.Cert, nil }
func (a *Auth) loadCertFromDir(dir string) (*tls.Certificate, error) { // Load cert from file keyFile := filepath.Join(dir, "key.pem") keyBytes, err := ioutil.ReadFile(keyFile) if err != nil { return nil, err } certBytes, err := ioutil.ReadFile(filepath.Join(dir, "cert-chain.pem")) if err != nil { return nil, err } tlsCert, err := tls.X509KeyPair(certBytes, keyBytes) if err != nil { return nil, err } if tlsCert.Certificate == nil || len(tlsCert.Certificate) == 0 { return nil, errors.New("missing certificate") } tlsCert.Leaf, _ = x509.ParseCertificate(tlsCert.Certificate[0]) return &tlsCert, nil }
func (a *Auth) waitAndInitFromDir() error { if a.CertDir == "" { a.CertDir = "./var/run/secrets/istio.io/" } keyFile := filepath.Join(a.CertDir, "key.pem") err := waitFile(keyFile, 5*time.Second) if err != nil { return err } err = a.initFromDir() if err != nil { return err } time.AfterFunc(30*time.Minute, a.initFromDirPeriodic) return nil }
func (a *Auth) initFromDirPeriodic() { err := a.initFromDir() if err != nil { log.Println("certRefresh", err) } time.AfterFunc(30*time.Minute, a.initFromDirPeriodic) }
func (a *Auth) initFromDir() error {
if a.Cert == nil { _, err := a.GetCertificate(context.Background(), "") if err != nil { return err } } rootCert, _ := ioutil.ReadFile(filepath.Join(a.CertDir, "root-cert.pem")) if rootCert != nil { err2 := a.AddRoots(rootCert) if err2 != nil { return err2 } } istioCert, _ := ioutil.ReadFile("./var/run/secrets/istio/root-cert.pem") if istioCert != nil { err2 := a.AddRoots(istioCert) if err2 != nil { return err2 } } // Similar with /etc/ssl/certs/ca-certificates.crt - the concatenated list of PEM certs. rootCertExtra, _ := ioutil.ReadFile(filepath.Join(a.CertDir, "ca-certificates.crt")) if rootCertExtra != nil { err2 := a.AddRoots(rootCertExtra) if err2 != nil { return err2 } } // If the certificate has a chain, use the last cert - similar with Istio if len(a.Cert.Certificate) > 1 { last := a.Cert.Certificate[len(a.Cert.Certificate)-1] rootCAs, err := x509.ParseCertificates(last) if err == nil { for _, c := range rootCAs { log.Println("Adding root CA from cert chain: ", c.Subject) a.TrustedCertPool.AddCert(c) } } } a.initTLS() return nil }
// InitRoots will find the mesh roots. // // - if Zatar or another CSI provider are enabled, we do nothing - Zatar config is the root of trust for everything // - otherwise the roots are expected to be part of mesh-env. The mesh connector or other tools will // populate it - ideally from the CSI/Zatar or TrustConfig CRD.
func (kr *Auth) InitRoots(ctx context.Context, outDir string) error { if outDir != "" { rootFile := filepath.Join(outDir, WorkloadRootCAs) rootCertPEM, err := ioutil.ReadFile(rootFile) if err == nil { block, rest := pem.Decode(rootCertPEM) var blockBytes []byte for block != nil { blockBytes = append(blockBytes, block.Bytes...) block, rest = pem.Decode(rest) } rootCAs, err := x509.ParseCertificates(blockBytes) if err != nil { return err } for _, c := range rootCAs { kr.TrustedCertPool.AddCert(c) } return nil } } // File not found - extract it from mesh env, and save it. // This includes Citadel root (if active in the mesh) or other roots. roots := "" block, rest := pem.Decode([]byte(roots)) var blockBytes []byte for block != nil { blockBytes = append(blockBytes, block.Bytes...) block, rest = pem.Decode(rest) } rootCAs, err := x509.ParseCertificates(blockBytes) if err != nil { return err } for _, c := range rootCAs { kr.TrustedCertPool.AddCert(c) } return nil }
// TODO: save last cert in the chain to roots
// 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 load 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 (kr *Auth) InitCertificates(ctx context.Context, certDir string) error { if certDir == "" { certDir = WorkloadCertDir } var err error keyFile := filepath.Join(certDir, privateKey) chainFile := filepath.Join(certDir, cert) kr.privPEM, err = ioutil.ReadFile(keyFile) kr.certPEM, err = ioutil.ReadFile(chainFile) kp, err := tls.X509KeyPair(kr.certPEM, kr.privPEM) if err == nil && len(kp.Certificate) > 0 { kr.CertDir = certDir kp.Leaf, _ = x509.ParseCertificate(kp.Certificate[0]) exp := kp.Leaf.NotAfter.Sub(time.Now()) if exp > -5*time.Minute { kr.Cert = &kp log.Println("Existing Cert", "expires", exp) return nil } } return nil }
Extract the trustDomain, namespace and Name from a spiffee certificate
func (*Auth) VAPIDToken ¶
VAPIDToken creates a token with the specified endpoint, using configured Sub id and a default expiration (1h).
Format is "vapid t=TOKEN k=PUBKEY
The optional (unauthenticated) Sub field is populated from Name@Domain or TrustDomain. The DMesh VIP is based on the public key of the signer. AUD is the URL from the subscription - for DMesh https://VIP:5228/s or https://DOMAIN:5228/s
type AuthConfig ¶
type AuthConfig struct { // ProjectNumber is required - this code doesn't look it up. // Set as x-goog-user-project ProjectNumber string // TrustDomain to use - typically based on project name. TrustDomain string // GKE Cluster address. // https://container.googleapis.com/v1/projects/%s/locations/%s/clusters/%s // It is also the iss field in the token. ClusterAddress string // TokenSource returns K8S or federated tokens with a given audience. TokenSource TokenSource }
AuthConfig contains the settings for getting tokens using K8S or federated tokens.
type ConfStore ¶
type ConfStore interface { // Get a config blob by name Get(name string) ([]byte, error) // Save a config blob Set(conf string, data []byte) error // List the configs starting with a prefix, of a given type List(name string, tp string) ([]string, error) }
Interface for very simple configuration and key loading. Can have a simple in-memory, fs implementation, as well as K8S, XDS or database backends.
The name is hierachical, in case of K8S or Istio corresponds to the type, including namespace.
type Context ¶
type Context struct { // Cluster is the name of the cluster for this context Cluster string `json:"cluster"` // AuthInfo is the name of the authInfo for this context User string `json:"user"` // Namespace is the default namespace to use on unspecified requests // +optional Namespace string `json:"namespace,omitempty"` }
Context is a tuple of references to a cluster (how do I communicate with a kubernetes cluster), a user (how do I identify myself), and a namespace (what subset of resources do I want to work with)
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 EncryptionContext ¶
type EncryptionContext struct { // Full body of the encrypted message, including header (salt, server pub) // Format: // 16 B Salt // 4B rs {0,0, 16, 0} - 4k // 1B ID-Size {65} // 65B SendPublicKey // Up to 4k encrypted text - with 0x02 appended at the end before encryption // Wasted: 7 const. // Overhead: 16 salt, 16 sig, 64 pub. Total: 103 (64+32+7) Ciphertext []byte // 16B For encryption: must be a random generated by sender. Salt []byte // Temp EC key for encryption, 65B SendPublic []byte // UA Public bytes - from subscription UAPublic []byte // Only used for encrypt SendPrivate []byte // Only used for decrypt UAPrivate []byte // Auth - from subscription Auth []byte // contains filtered or unexported fields }
EncryptionContext stores the source and result of encrypting a message. The ciphertext is the actual encrypted message, while the salt and server public key are required to be sent to the client so that the message can be decrypted.
func NewContextSend ¶
func NewContextSend(uapub, auth []byte) *EncryptionContext
func NewContextUA ¶
func NewContextUA(uapriv, uapub, auth []byte) *EncryptionContext
Deprecated, test only
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. Sub string `json:"sub,omitempty"` // Max 24h Exp int64 `json:"exp,omitempty"` IAT int64 `json:"iat,omitempty"` // Issuer - for example kubernetes/serviceaccount. Iss string `json:"iss,omitempty"` Email string `json:"email,omitempty"` EmailVerified bool `json:"email_verified,omitempty"` K8S K8SAccountInfo `json:"kubernetes.io"` Name string `json:"kubernetes.io/serviceaccount/service-account.name"` Raw string `json:-` }
JWT includes minimal field for a JWT, primarily for extracting iss for the exchange. This is used with K8S JWTs, which use multi-string.
func CheckVAPID ¶
CheckVAPID verifies the signature and returns the token and public key. expCheck should be set to current time to set expiration
Data is extracted from VAPID header - 'vapid' scheme and t/k params
Does not check audience or other parms.
type JWTRule ¶
type JWTRule struct { // Example: https://foobar.auth0.com // Example: 1234567-compute@developer.gserviceaccount.com Issuer string `protobuf:"bytes,1,opt,name=issuer,proto3" json:"issuer,omitempty"` // The list of JWT // [audiences](https://tools.ietf.org/html/rfc7519#section-4.1.3). // that are allowed to access. A JWT containing any of these // audiences will be accepted. // // The service name will be accepted if audiences is empty. // // Example: // // “`yaml // audiences: // - bookstore_android.apps.example.com // bookstore_web.apps.example.com // “` Audiences []string `protobuf:"bytes,2,rep,name=audiences,proto3" json:"audiences,omitempty"` // URL of the provider's public key set to validate signature of the // JWT. See [OpenID Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata). // // Optional if the key set document can either (a) be retrieved from // [OpenID // Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) of // the issuer or (b) inferred from the email domain of the issuer (e.g. a // Google service account). // // Example: `https://www.googleapis.com/oauth2/v1/certs` // // Note: Only one of jwks_uri and jwks should be used. jwks_uri will be ignored if it does. JwksUri string `protobuf:"bytes,3,opt,name=jwks_uri,json=jwksUri,proto3" json:"jwks_uri,omitempty"` }
JWTRule - from istio API, as json.
type K8SAccountInfo ¶
type K8SAccountInfo struct {
Namespace string `json:"namespace"`
}
type KubeCluster ¶
type KubeCluster struct { // LocationOfOrigin indicates where this object came from. It is used for round tripping config post-merge, but never serialized. // +k8s:conversion-gen=false //LocationOfOrigin string // Server is the address of the kubernetes cluster (https://hostname:port). Server string `json:"server"` // InsecureSkipTLSVerify skips the validity check for the server's certificate. This will make your HTTPS connections insecure. // +optional InsecureSkipTLSVerify bool `json:"insecure-skip-tls-verify,omitempty"` // CertificateAuthority is the path to a cert file for the certificate authority. // +optional CertificateAuthority string `json:"certificate-authority,omitempty" yaml:"certificate-authority"` // CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthority // +optional CertificateAuthorityData string `json:"certificate-authority-data,omitempty" yaml:"certificate-authority-data"` }
type KubeConfig ¶
type KubeConfig struct { // Must be v1 ApiVersion string `json:"apiVersion"` // Must be Config Kind string `json:"kind"` // Clusters is a map of referencable names to cluster configs Clusters []KubeNamedCluster `json:"clusters"` // AuthInfos is a map of referencable names to user configs Users []KubeNamedUser `json:"users"` // Contexts is a map of referencable names to context configs Contexts []KubeNamedContext `json:"contexts"` // CurrentContext is the name of the context that you would like to use by default CurrentContext string `json:"current-context" yaml:"current-context"` }
KubeConfig is the JSON representation of the kube config. The format supports most of the things we need and also allows connection to real k8s clusters. UGate implements a very light subset - should be sufficient to connect to K8S, but without any generated stubs. Based in part on https://github.com/ericchiang/k8s (abandoned), which is a light client.
type KubeNamedCluster ¶
type KubeNamedCluster struct { Name string `json:"name"` Cluster KubeCluster `json:"cluster"` }
type KubeNamedContext ¶
type KubeNamedUser ¶
type KubeUser ¶
type KubeUser struct { // LocationOfOrigin indicates where this object came from. It is used for round tripping config post-merge, but never serialized. // +k8s:conversion-gen=false //LocationOfOrigin string // ClientCertificate is the path to a client cert file for TLS. // +optional ClientCertificate string `json:"client-certificate,omitempty"` // ClientCertificateData contains PEM-encoded data from a client cert file for TLS. Overrides ClientCertificate // +optional ClientCertificateData []byte `json:"client-certificate-data,omitempty"` // ClientKey is the path to a client key file for TLS. // +optional ClientKey string `json:"client-key,omitempty"` // ClientKeyData contains PEM-encoded data from a client key file for TLS. Overrides ClientKey // +optional ClientKeyData []byte `json:"client-key-data,omitempty"` // Token is the bearer token for authentication to the kubernetes cluster. // +optional Token string `json:"token,omitempty"` // TokenFile is a pointer to a file that contains a bearer token (as described above). If both Token and TokenFile are present, Token takes precedence. // +optional TokenFile string `json:"tokenFile,omitempty"` // Impersonate is the username to act-as. // +optional //Impersonate string `json:"act-as,omitempty"` // ImpersonateGroups is the groups to imperonate. // +optional //ImpersonateGroups []string `json:"act-as-groups,omitempty"` // ImpersonateUserExtra contains additional information for impersonated user. // +optional //ImpersonateUserExtra map[string][]string `json:"act-as-user-extra,omitempty"` // Username is the username for basic authentication to the kubernetes cluster. // +optional Username string `json:"username,omitempty"` // Password is the password for basic authentication to the kubernetes cluster. // +optional Password string `json:"password,omitempty"` // AuthProvider specifies a custom authentication plugin for the kubernetes cluster. // +optional AuthProvider UserAuthProvider `json:"auth-provider,omitempty" yaml:"auth-provider,omitempty"` }
KubeUser contains information that describes identity information. This is use to tell the kubernetes cluster who you are.
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 RemoteID ¶
func RemoteIDmTLS ¶
type ReqContext ¶
type ReqContext struct { // Auth role - set if a authorized_keys or other authz is configured Role string // SAN list from the certificate, or equivalent auth method. SAN []string // Request start time T0 time.Time // Public key of the first cert in the chain (similar with SSH) Pub []byte // VIP associated with the public key. VIP net.IP VAPID *JWT }
func AuthContext ¶
func AuthContext(ctx context.Context) *ReqContext
func (*ReqContext) ID ¶
func (rc *ReqContext) ID() string
ID of the caller, validated based on certs. Currently based on VIP6 for mesh nods.
type STS ¶
type STS struct { // Google service account to impersonate and return tokens for. // The KSA returned from K8S must have the IAM permissions GSA string AudOverride string // K8S returns a token signed by k8s, no further exchanges. K8S bool // UseSTSExchange will return a token for an external service account. UseSTSExchange bool // UseAccessToken will force returning a GSA access token, regardless of audience. UseAccessToken bool // contains filtered or unexported fields }
STS provides token exchanges. Implements grpc and golang.org/x/oauth2.TokenSource The source of trust is the K8S token with TrustDomain audience, it is exchanged with access or ID tokens.
func NewFederatedTokenSource ¶
func NewFederatedTokenSource(kr *AuthConfig) *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.
func NewGSATokenSource ¶
func NewGSATokenSource(kr *AuthConfig, gsa string) *STS
NewGSATokenSource returns a oauth2.TokenSource and grpc credentials.PerRPCCredentials implmentation, returning access tokens for a Google Service Account.
If the gsa is empty, the ASM mesh P4SA will be used instead. This is suitable for connecting to stackdriver and out-of-cluster managed Istiod. Otherwise, the gsa must grant the KSA (kubernetes service account) permission to act as the GSA.
func NewK8STokenSource ¶
func NewK8STokenSource(kr *AuthConfig, audOverride string) *STS
NewK8STokenSource returns a oauth2 and grpc token source that returns K8S signed JWTs with the given audience.
func NewSTS ¶
func NewSTS(kr *AuthConfig) (*STS, error)
func (*STS) ExternalSA ¶
func (*STS) GetRequestMetadata ¶
GetRequestMetadata implements credentials.PerRPCCredentials This can be used for both ID tokens or access tokens - if the 'aud' containts googleapis.com, access tokens are returned.
func (*STS) RequireTransportSecurity ¶
func (*STS) ServeStsRequests ¶
func (s *STS) ServeStsRequests(w http.ResponseWriter, req *http.Request)
ServeStsRequests handles STS requests and sends exchanged token in responses.
func (*STS) TokenAccess ¶
func (s *STS) TokenAccess(ctx context.Context, federatedToken string, audience string) (string, error)
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 ID token with aud or access token.
type StsErrorResponse ¶
type StsErrorResponse struct { // REQUIRED. A single ASCII Error code. Error string `json:"error"` // OPTIONAL. Human-readable ASCII [USASCII] text providing additional information. ErrorDescription string `json:"error_description"` // OPTIONAL. A URI identifying a human-readable web page with information // about the Error. ErrorURI string `json:"error_uri"` }
StsErrorResponse stores all Error parameters sent as JSON in a STS Error response. The Error parameters are defined in https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16#section-2.2.2.
type StsRequestParameters ¶
type StsRequestParameters struct { // REQUIRED. The value "urn:ietf:params:oauth:grant-type:token- exchange" // indicates that a token exchange is being performed. GrantType string // OPTIONAL. Indicates the location of the target service or resource where // the client intends to use the requested security token. Resource string // OPTIONAL. The logical name of the target service where the client intends // to use the requested security token. Audience string // OPTIONAL. A list of space-delimited, case-sensitive strings, that allow // the client to specify the desired Scope of the requested security token in the // context of the service or Resource where the token will be used. Scope string // OPTIONAL. An identifier, for the type of the requested security token. RequestedTokenType string // REQUIRED. A security token that represents the identity of the party on // behalf of whom the request is being made. SubjectToken string // REQUIRED. An identifier, that indicates the type of the security token in // the "subject_token" parameter. SubjectTokenType string // OPTIONAL. A security token that represents the identity of the acting party. ActorToken string // An identifier, that indicates the type of the security token in the // "actor_token" parameter. ActorTokenType string }
StsRequestParameters stores all STS request attributes defined in https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16#section-2.1
type StsResponseParameters ¶
type StsResponseParameters 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"` }
StsResponseParameters stores all attributes sent as JSON in a successful STS response. These attributes are defined in https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16#section-2.2.1
type Subscription ¶
type Subscription struct { // Endpoint is the URL to send the Web Push message to. Comes from the // endpoint field of the PushSubscription. Endpoint string // Key is the client's public key. From the getKey("p256dh") or keys.p256dh field. Key []byte // Auth is a value used by the client to validate the encryption. From the // keys.auth field. // The encrypted aes128gcm will have 16 bytes authentication tag derived from this. // This is the pre-shared authentication secret. Auth []byte // Used by the UA to receive messages, as PUSH promises Location string }
Subscription holds the useful values from a PushSubscription object acquired from the browser.
https://w3c.github.io/push-api/
Returned as result of /subscribe
func SubscriptionFromJSON ¶
func SubscriptionFromJSON(b []byte) (*Subscription, error)
SubscriptionFromJSON is a convenience function that takes a JSON encoded PushSubscription object acquired from the browser and returns a pointer to a node.
type TokenCache ¶
type TokenCache struct {
// contains filtered or unexported fields
}
func NewTokenCache ¶
func NewTokenCache(sts *STS) *TokenCache
type TokenSource ¶
type UserAuthProvider ¶
type UserAuthProvider struct {
Name string `json:"name,omitempty"`
}