// Helper function to perform a remote sign or info request. func (s *Signer) remoteOp(req interface{}, profile, target string) (resp interface{}, err error) { jsonData, err := json.Marshal(req) if err != nil { return nil, cferr.Wrap(cferr.APIClientError, cferr.JSONError, err) } p, err := signer.Profile(s, profile) if err != nil { return } server := client.NewServerTLS(p.RemoteServer, helpers.CreateTLSConfig(p.RemoteCAs, p.ClientCert)) if server == nil { return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest, errors.New("failed to connect to remote")) } // There's no auth provider for the "info" method if target == "info" { resp, err = server.Info(jsonData) } else if p.RemoteProvider != nil { resp, err = server.AuthSign(jsonData, nil, p.RemoteProvider) } else { resp, err = server.Sign(jsonData) } if err != nil { return nil, err } return }
func getInfoFromRemote(c cli.Config) (resp *info.Resp, err error) { req := new(info.Req) req.Label = c.Label req.Profile = c.Profile cert, err := helpers.LoadClientCertificate(c.MutualTLSCertFile, c.MutualTLSKeyFile) if err != nil { return } remoteCAs, err := helpers.LoadPEMCertPool(c.TLSRemoteCAs) if err != nil { return } serv := client.NewServerTLS(c.Remote, helpers.CreateTLSConfig(remoteCAs, cert)) reqJSON, _ := json.Marshal(req) resp, err = serv.Info(reqJSON) if err != nil { return } _, err = helpers.ParseCertificatePEM([]byte(resp.Certificate)) if err != nil { return } return }
func NewTLSServerGroup(t *testing.T, cert *tls.Certificate) { s := NewServerTLS("https://cfssl1.local:8888, https://cfssl2.local:8888", helpers.CreateTLSConfig(nil, cert)) ogl, ok := s.(*orderedListGroup) if !ok { t.Fatalf("expected NewServer to return an ordered group list with a list of servers, instead got a %T = %+v", ogl, ogl) } if len(ogl.remotes) != 2 { t.Fatalf("expected the remote to have two servers, but it has %d", len(ogl.remotes)) } hosts := ogl.Hosts() if len(hosts) != 2 { t.Fatalf("expected 2 hosts in the group, but have %d", len(hosts)) } if hosts[0] != "https://cfssl1.local:8888" { t.Fatalf("expected to see https://cfssl1.local:8888, but saw %s", hosts[0]) } if hosts[1] != "https://cfssl2.local:8888" { t.Fatalf("expected to see https://cfssl2.local:8888, but saw %s", hosts[1]) } }
// NewCFSSL produces a new CFSSL root. func NewCFSSL(metadata map[string]string) ([]*x509.Certificate, error) { host, ok := metadata["host"] if !ok { return nil, errors.New("transport: CFSSL root provider requires a host") } label := metadata["label"] profile := metadata["profile"] cert, err := helpers.LoadClientCertificate(metadata["mutual-tls-cert"], metadata["mutual-tls-key"]) if err != nil { return nil, err } remoteCAs, err := helpers.LoadPEMCertPool(metadata["tls-remote-ca"]) if err != nil { return nil, err } srv := client.NewServerTLS(host, helpers.CreateTLSConfig(remoteCAs, cert)) data, err := json.Marshal(info.Req{Label: label, Profile: profile}) if err != nil { return nil, err } resp, err := srv.Info(data) if err != nil { return nil, err } return helpers.ParseCertificatesPEM([]byte(resp.Certificate)) }
func TestNewMutualTLSServer(t *testing.T) { cert, _ := helpers.LoadClientCertificate("../../helpers/testdata/ca.pem", "../../helpers/testdata/ca_key.pem") s := NewServerTLS("https://nohost:8888", helpers.CreateTLSConfig(nil, cert)) if s == nil { t.Fatalf("fatal error, empty server") } _, err := s.Sign([]byte{5, 5, 5, 5}) if err == nil { t.Fatalf("expected error with sign function") } if !strings.Contains(err.Error(), "Post https://nohost:8888/api/v1/cfssl/sign: dial tcp: lookup nohost") { t.Fatalf("no error message %v", err) } }
// NewCFSSLProvider takes the configuration information from an // Identity (and an optional default remote), returning a CFSSL // instance. There should be a profile in id called "cfssl", which // should contain label and profile fields as needed. func NewCFSSLProvider(id *core.Identity, defaultRemote client.Remote) (*CFSSL, error) { if id == nil { return nil, errors.New("transport: the identity hasn't been initialised. Has it been loaded from disk?") } cap := &CFSSL{ DefaultRemote: defaultRemote, } cfssl := id.Profiles["cfssl"] if cfssl != nil { cap.Label = cfssl["label"] cap.Profile = cfssl["profile"] if cap.DefaultRemote == nil { cert, err := helpers.LoadClientCertificate(cfssl["mutual-tls-cert"], cfssl["mutual-tls-key"]) if err != nil { return nil, err } remoteCAs, err := helpers.LoadPEMCertPool(cfssl["tls-remote-ca"]) if err != nil { return nil, err } cap.DefaultRemote = client.NewServerTLS(cfssl["remote"], helpers.CreateTLSConfig(remoteCAs, cert)) } cap.DefaultAuth.Type = cfssl["auth-type"] cap.DefaultAuth.Key = cfssl["auth-key"] } err := cap.setRemoteAndAuth() if err != nil { return nil, err } return cap, nil }
func (cap *CFSSL) setRemoteAndAuth() error { if cap.Label != "" { cfsslConfig := findLabel(cap.Label) profile, ok := getProfile(cfsslConfig, cap.Profile) if ok { remote, ok := getRemote(cfsslConfig, profile) if ok { cap.remote = client.NewServerTLS(remote, helpers.CreateTLSConfig(profile.RemoteCAs, profile.ClientCert)) cap.provider = profile.Provider return nil } // The profile may not have a remote set, but // it may have an authentication provider. cap.provider = profile.Provider } } cap.remote = cap.DefaultRemote if cap.provider != nil { return nil } return cap.loadAuth() }