Example #1
0
func main() {
	key, err := libtrust.LoadKeyFile(clientPrivateKeyFilename)
	if err != nil {
		log.Fatal(err)
	}

	keyPEMBlock, err := key.PEMBlock()
	if err != nil {
		log.Fatal(err)
	}

	encodedPrivKey := pem.EncodeToMemory(keyPEMBlock)
	fmt.Printf("Client Key:\n\n%s\n", string(encodedPrivKey))

	cert, err := libtrust.GenerateSelfSignedClientCert(key)
	if err != nil {
		log.Fatal(err)
	}

	encodedCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
	fmt.Printf("Client Cert:\n\n%s\n", string(encodedCert))

	trustedServerKeys, err := libtrust.LoadKeySetFile(trustedHostsFilename)
	if err != nil {
		log.Fatal(err)
	}

	hostname, _, err := net.SplitHostPort(serverAddress)
	if err != nil {
		log.Fatal(err)
	}

	trustedServerKeys, err = libtrust.FilterByHosts(trustedServerKeys, hostname, false)
	if err != nil {
		log.Fatal(err)
	}

	caCert, err := libtrust.GenerateCACert(key, trustedServerKeys[0])
	if err != nil {
		log.Fatal(err)
	}

	encodedCert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: caCert.Raw})
	fmt.Printf("CA Cert:\n\n%s\n", string(encodedCert))
}
Example #2
0
// NewIdentityAuthTLSConfig creates a tls.Config for the client to use for
// libtrust identity authentication
func NewIdentityAuthTLSConfig(trustKey libtrust.PrivateKey, knownHostsPath, proto, addr string) (*tls.Config, error) {
	tlsConfig := createTLSConfig()

	// Load known hosts
	knownHosts, err := libtrust.LoadKeySetFile(knownHostsPath)
	if err != nil {
		return nil, fmt.Errorf("Could not load trusted hosts file: %s", err)
	}

	// Generate CA pool from known hosts
	allowedHosts, err := libtrust.FilterByHosts(knownHosts, addr, false)
	if err != nil {
		return nil, fmt.Errorf("Error filtering hosts: %s", err)
	}
	certPool, err := libtrust.GenerateCACertPool(trustKey, allowedHosts)
	if err != nil {
		return nil, fmt.Errorf("Could not create CA pool: %s", err)
	}
	tlsConfig.ServerName = "docker"
	tlsConfig.RootCAs = certPool

	// Generate client cert from trust key
	x509Cert, err := libtrust.GenerateSelfSignedClientCert(trustKey)
	if err != nil {
		return nil, fmt.Errorf("Certificate generation error: %s", err)
	}
	tlsConfig.Certificates = []tls.Certificate{{
		Certificate: [][]byte{x509Cert.Raw},
		PrivateKey:  trustKey.CryptoPrivateKey(),
		Leaf:        x509Cert,
	}}

	// Connect to server to see if it is a known host
	tlsConfig.InsecureSkipVerify = true
	testConn, err := tls.Dial(proto, addr, tlsConfig)
	if err != nil {
		return nil, fmt.Errorf("TLS Handshake error: %s", err)
	}
	opts := x509.VerifyOptions{
		Roots:         tlsConfig.RootCAs,
		CurrentTime:   time.Now(),
		DNSName:       tlsConfig.ServerName,
		Intermediates: x509.NewCertPool(),
	}

	certs := testConn.ConnectionState().PeerCertificates
	for i, cert := range certs {
		if i == 0 {
			continue
		}
		opts.Intermediates.AddCert(cert)
	}
	_, err = certs[0].Verify(opts)
	if err != nil {
		if _, ok := err.(x509.UnknownAuthorityError); ok {
			pubKey, err := libtrust.FromCryptoPublicKey(certs[0].PublicKey)
			if err != nil {
				return nil, fmt.Errorf("Error extracting public key from certificate: %s", err)
			}

			// If server is not a known host, prompt user to ask whether it should
			// be trusted and add to the known hosts file
			if promptUnknownKey(pubKey, addr) {
				pubKey.AddExtendedField("hosts", []string{addr})
				err = libtrust.AddKeySetFile(knownHostsPath, pubKey)
				if err != nil {
					return nil, fmt.Errorf("Error saving updated host keys file: %s", err)
				}

				ca, err := libtrust.GenerateCACert(trustKey, pubKey)
				if err != nil {
					return nil, fmt.Errorf("Error generating CA: %s", err)
				}
				tlsConfig.RootCAs.AddCert(ca)
			} else {
				return nil, fmt.Errorf("Cancelling request due to invalid certificate")
			}
		} else {
			return nil, fmt.Errorf("TLS verification error: %s", err)
		}
	}

	testConn.Close()
	tlsConfig.InsecureSkipVerify = false

	return tlsConfig, nil
}
Example #3
0
func main() {
	// Load Client Key.
	clientKey, err := libtrust.LoadKeyFile(privateKeyFilename)
	if err != nil {
		log.Fatal(err)
	}

	// Generate Client Certificate.
	selfSignedClientCert, err := libtrust.GenerateSelfSignedClientCert(clientKey)
	if err != nil {
		log.Fatal(err)
	}

	// Load trusted host keys.
	hostKeys, err := libtrust.LoadKeySetFile(trustedHostsFilename)
	if err != nil {
		log.Fatal(err)
	}

	// Ensure the host we want to connect to is trusted!
	host, _, err := net.SplitHostPort(serverAddress)
	if err != nil {
		log.Fatal(err)
	}
	serverKeys, err := libtrust.FilterByHosts(hostKeys, host, false)
	if err != nil {
		log.Fatalf("%q is not a known and trusted host", host)
	}

	// Generate a CA pool with the trusted host's key.
	caPool, err := libtrust.GenerateCACertPool(clientKey, serverKeys)
	if err != nil {
		log.Fatal(err)
	}

	// Create HTTP Client.
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				Certificates: []tls.Certificate{
					tls.Certificate{
						Certificate: [][]byte{selfSignedClientCert.Raw},
						PrivateKey:  clientKey.CryptoPrivateKey(),
						Leaf:        selfSignedClientCert,
					},
				},
				RootCAs: caPool,
			},
		},
	}

	var makeRequest = func(url string) {
		resp, err := client.Get(url)
		if err != nil {
			log.Fatal(err)
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Fatal(err)
		}

		log.Println(resp.Status)
		log.Println(string(body))
	}

	// Make the request to the trusted server!
	makeRequest(fmt.Sprintf("https://%s", serverAddress))
}