Skip to content

Commit

Permalink
Add ssh key pair bait to sandbox (#916)
Browse files Browse the repository at this point in the history
* Add ssh key pair bait to sandbox

Signed-off-by: Elaine Chien <elainechien@google.com>

* Add documentation and temp dir edits

Signed-off-by: Elaine Chien <elainechien@google.com>

* Add space

Signed-off-by: Elaine Chien <elainechien@google.com>

* Log error but don't fail if adding ssh keys results in an error

Signed-off-by: Elaine Chien <elainechien@google.com>

---------

Signed-off-by: Elaine Chien <elainechien@google.com>
  • Loading branch information
elainechien authored Oct 24, 2023
1 parent 4c90774 commit 6db7dcb
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
47 changes: 47 additions & 0 deletions internal/worker/rundynamic.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package worker

import (
"context"
"crypto/rand"
"crypto/rsa"
"encoding/pem"
"fmt"
"io"
"log/slog"
Expand All @@ -20,6 +23,7 @@ import (
"github.com/ossf/package-analysis/internal/sandbox"
"github.com/ossf/package-analysis/pkg/api/analysisrun"
"github.com/ossf/package-analysis/pkg/api/pkgecosystem"
"golang.org/x/crypto/ssh"
)

// defaultDynamicAnalysisImage is container image name of the default dynamic analysis sandbox
Expand Down Expand Up @@ -66,6 +70,44 @@ func dynamicPhases(ecosystem pkgecosystem.Ecosystem) []analysisrun.DynamicPhase
return phases
}

// addSSHKeysToSandbox generates a new rsa private and public key pair
// and copies them into the ~/.ssh directory of the sandbox with the
// default file names.
func addSSHKeysToSandbox(ctx context.Context, sb sandbox.Sandbox) error {
generatedPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
generatedPublicKey := generatedPrivateKey.PublicKey
if err != nil {
return err
}

tempdir, err := os.MkdirTemp(".", "temp_ssh_dir")
if err != nil {
return err
}
defer os.RemoveAll(tempdir)
privateKeyFile, err := os.Create(filepath.Join(tempdir, "id_rsa"))
if err != nil {
return err
}
defer privateKeyFile.Close()
pubKeyFile, err := os.Create(filepath.Join(tempdir, "id_rsa.pub"))
if err != nil {
return err
}
defer pubKeyFile.Close()

openSSHPrivateKeyBlock, err := ssh.MarshalPrivateKey(generatedPrivateKey, "")
if err = pem.Encode(privateKeyFile, openSSHPrivateKeyBlock); err != nil {
return err
}
publicKey, err := ssh.NewPublicKey(&generatedPublicKey)
if err != nil {
return err
}
pubKeyFile.Write(ssh.MarshalAuthorizedKey(publicKey))
return sb.CopyIntoSandbox(ctx, tempdir+"/.", "/root/.ssh")
}

/*
RunDynamicAnalysis runs dynamic analysis on the given package across the phases
valid in the package ecosystem (e.g. import, install), in a sandbox created
Expand Down Expand Up @@ -109,6 +151,11 @@ func RunDynamicAnalysis(ctx context.Context, pkg *pkgmanager.Pkg, sbOpts []sandb
return DynamicAnalysisResult{}, err
}

if err := addSSHKeysToSandbox(ctx, sb); err != nil {
// Log error and proceed without ssh keys.
LogDynamicAnalysisError(ctx, pkg, "", err)
}

result := DynamicAnalysisResult{
AnalysisData: analysisrun.DynamicAnalysisResults{
StraceSummary: make(analysisrun.DynamicAnalysisStraceSummary),
Expand Down
2 changes: 2 additions & 0 deletions sample_packages/sample_python_package/src/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ def access_ssh_keys(called_from: str, print_logs: bool) -> None:
# Fail gracefully to allow execution to continue.
if print_logs:
print(f"An exception occurred when calling access_ssh_keys: {str(e)}")
elif print_logs:
print("Could not locate ssh key directory.")

def read_file_and_log(file_to_read: str, called_from: str, print_logs: bool) -> None:
if os.path.isfile(file_to_read):
Expand Down

0 comments on commit 6db7dcb

Please sign in to comment.