Skip to content

Commit

Permalink
ostree: configurable MTLS config for ostree resolve
Browse files Browse the repository at this point in the history
  • Loading branch information
lzap committed Oct 17, 2024
1 parent 7b89d25 commit 8e5b68c
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 44 deletions.
20 changes: 19 additions & 1 deletion cmd/otk/osbuild-resolve-ostree-commit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"io"
"net/url"
"os"

"github.com/osbuild/images/internal/cmdutil"
Expand Down Expand Up @@ -49,7 +50,24 @@ func run(r io.Reader, w io.Writer) error {
return err
}

sourceSpec := ostree.SourceSpec(inputTree.Tree)
sourceSpec := ostree.SourceSpec{}
sourceSpec.URL = inputTree.Tree.URL
sourceSpec.Ref = inputTree.Tree.Ref
sourceSpec.RHSM = inputTree.Tree.RHSM
var proxy *url.URL
if proxyStr, ok := os.LookupEnv("OSBUILD_SOURCES_OSTREE_PROXY"); ok {
var err error
proxy, err = url.Parse(proxyStr)
if err != nil {
return fmt.Errorf("failed to parse proxy URL: %w", err)
}
}
sourceSpec.Connection = ostree.Connection{
CA: os.Getenv("OSBUILD_SOURCES_OSTREE_SSL_CA_CERT"),
MTLSClientKey: os.Getenv("OSBUILD_SOURCES_OSTREE_SSL_CLIENT_KEY"),
MTLSClientCert: os.Getenv("OSBUILD_SOURCES_OSTREE_SSL_CLIENT_CERT"),
Proxy: proxy,
}

var commitSpec ostree.CommitSpec
if !underTest() {
Expand Down
118 changes: 75 additions & 43 deletions pkg/ostree/ostree.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,20 @@ var (
// SourceSpec serves as input for ResolveParams, and contains all necessary
// variables to resolve a ref, which can then be turned into a CommitSpec.
type SourceSpec struct {
URL string
Ref string
RHSM bool
URL string
Ref string
// RHSM is deprecated, use Resolve function with MTLS configuration
RHSM bool
Connection Connection
}

// Connection contains the options for resolving an ostree source.
type Connection struct {
BaseURL *url.URL
CA string
MTLSClientKey string
MTLSClientCert string
Proxy *url.URL
}

// CommitSpec specifies an ostree commit using any combination of Ref (branch), URL (source), and Checksum (commit ID).
Expand Down Expand Up @@ -138,59 +149,50 @@ func verifyChecksum(commit string) bool {
return len(commit) > 0 && ostreeCommitRE.MatchString(commit)
}

// ResolveRef resolves the URL path specified by the location and ref
// ResolveRefMTLS resolves the URL path specified by the location and ref
// (location+"refs/heads/"+ref) and returns the commit ID for the named ref. If
// there is an error, it will be of type ResolveRefError.
func ResolveRef(location, ref string, consumerCerts bool, subs *rhsm.Subscriptions, ca *string) (string, error) {
// MTLS client cert, CA and HTTPS proxy are required for this function.
func ResolveRefMTLS(location, ref, caCert, cert, key string, proxy *url.URL) (string, error) {
u, err := url.Parse(location)
if err != nil {
return "", NewResolveRefError("error parsing ostree repository location: %v", err)
}
u.Path = path.Join(u.Path, "refs/heads/", ref)

var client *http.Client
if consumerCerts {
if subs == nil {
subs, err = rhsm.LoadSystemSubscriptions()
transport := http.DefaultTransport.(*http.Transport).Clone()
client := &http.Client{
Transport: transport,
Timeout: 300 * time.Second,
}
if u.Scheme == "https" {
tlsConf := &tls.Config{}

Check failure on line 169 in pkg/ostree/ostree.go

View workflow job for this annotation

GitHub Actions / ⌨ Lint

G402: TLS MinVersion too low. (gosec)

// If CA is set, load the CA certificate and add it to the TLS configuration. Otherwise, use the system CA.
if caCert != "" {
caCertPEM, err := os.ReadFile(caCert)
if err != nil {
return "", NewResolveRefError("error adding rhsm certificates when resolving ref: %s", err)
return "", NewResolveRefError("error adding ca certificate when resolving ref: %s", err)
}
if subs.Consumer == nil {
return "", NewResolveRefError("error adding rhsm certificates when resolving ref")
tlsConf.RootCAs = x509.NewCertPool()
if ok := tlsConf.RootCAs.AppendCertsFromPEM(caCertPEM); !ok {
return "", NewResolveRefError("error adding ca certificate when resolving ref")
}
}

tlsConf := &tls.Config{
MinVersion: tls.VersionTLS12,
}

if ca != nil {
caCertPEM, err := os.ReadFile(*ca)
if cert != "" && key != "" {
cert, err := tls.LoadX509KeyPair(cert, key)
if err != nil {
return "", NewResolveRefError("error adding rhsm certificates when resolving ref: %s", err)
return "", NewResolveRefError("error adding client certificate when resolving ref: %s", err)
}
roots := x509.NewCertPool()
ok := roots.AppendCertsFromPEM(caCertPEM)
if !ok {
return "", NewResolveRefError("error adding rhsm certificates when resolving ref")
}
tlsConf.RootCAs = roots
tlsConf.Certificates = []tls.Certificate{cert}
}

cert, err := tls.LoadX509KeyPair(subs.Consumer.ConsumerCert, subs.Consumer.ConsumerKey)
if err != nil {
return "", NewResolveRefError("error adding rhsm certificates when resolving ref: %s", err)
}
tlsConf.Certificates = []tls.Certificate{cert}
transport.TLSClientConfig = tlsConf
}

client = &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConf,
},
Timeout: 300 * time.Second,
}
} else {
client = &http.Client{}
transport.Proxy = func(request *http.Request) (*url.URL, error) {
return proxy, nil
}

req, err := http.NewRequest(http.MethodGet, u.String(), nil)
Expand Down Expand Up @@ -218,6 +220,33 @@ func ResolveRef(location, ref string, consumerCerts bool, subs *rhsm.Subscriptio
return checksum, nil
}

// ResolveRef is deprecated, use ResolveRefMTLS.
func ResolveRef(location, ref string, consumerCerts bool, subs *rhsm.Subscriptions, ca *string) (string, error) {
var err error
var caCert, consumerCert, consumerKey string

if consumerCerts {
if subs == nil {
subs, err = rhsm.LoadSystemSubscriptions()
if err != nil {
return "", NewResolveRefError("error adding rhsm certificates when resolving ref: %s", err)
}
if subs.Consumer == nil {
return "", NewResolveRefError("error adding rhsm certificates when resolving ref")
}
}

consumerCert = subs.Consumer.ConsumerCert
consumerKey = subs.Consumer.ConsumerKey
}

if ca != nil {
caCert = *ca
}

return ResolveRefMTLS(location, ref, caCert, consumerCert, consumerKey, nil)
}

// Resolve the ostree source specification to a commit specification.
//
// If a URL is defined in the source specification, the checksum of the ref is
Expand All @@ -234,10 +263,6 @@ func Resolve(source SourceSpec) (CommitSpec, error) {
URL: source.URL,
}

if source.RHSM {
commit.Secrets = "org.osbuild.rhsm.consumer"
}

if verifyChecksum(source.Ref) {
// the ref is a commit: return as is
commit.Checksum = source.Ref
Expand All @@ -252,7 +277,14 @@ func Resolve(source SourceSpec) (CommitSpec, error) {
// URL set: Resolve checksum
if source.URL != "" {
// If a URL is specified, we need to fetch the commit at the URL.
checksum, err := ResolveRef(source.URL, source.Ref, source.RHSM, nil, nil)
checksum, err := ResolveRefMTLS(
source.URL,
source.Ref,
source.Connection.CA,
source.Connection.MTLSClientCert,
source.Connection.MTLSClientKey,
source.Connection.Proxy,
)
if err != nil {
return CommitSpec{}, err // ResolveRefError
}
Expand Down

0 comments on commit 8e5b68c

Please sign in to comment.