Skip to content

Commit

Permalink
Merge branch 'main' into rarguellof/APPSEC-53279/add-support-aws-sdk-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
rarguelloF committed Aug 29, 2024
2 parents 0d57420 + f109ee0 commit 21b6817
Show file tree
Hide file tree
Showing 44 changed files with 1,470 additions and 538 deletions.
12 changes: 11 additions & 1 deletion .github/workflows/workflow_call.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,22 @@ on:
required: false
type: string
default: main
runs-on:
description: 'The runner to use for the job'
required: false
type: string
default: ubuntu-latest
workflow_call:
inputs:
dd-trace-go-ref:
type: string
required: true
description: 'The ref to checkout dd-trace-go at'
runs-on:
description: 'The runner to use for the job'
required: false
type: string
default: ubuntu-latest

permissions: read-all

Expand All @@ -22,7 +32,7 @@ concurrency:

jobs:
integration-tests:
runs-on: ubuntu-latest-16-cores
runs-on: ${{ inputs.runs-on }}
name: Integration Smoke Tests
steps:
- name: Checkout orchestrion
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
orchestrion
coverage/
venv/
.python-version
68 changes: 10 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Automatic compile-time instrumentation of Go code.

[Orchestrion](https://en.wikipedia.org/wiki/Orchestrion) processes Go source code at compilation time and automatically
inserts instrumentation. This instrumentation produces Datadog APM traces from the instrumented code and supports
Datadog Application Security Management. Future work will include support for OpenTelemetry tracing as well.
Datadog Application Security Management.

> [!IMPORTANT]
> Orchestrion is under active development. The supported features are rapidly growing, and the user experiece may evolve
Expand Down Expand Up @@ -113,63 +113,6 @@ In addition to this, Orchestrion only supports projects using [Go modules][go-mo
> $ go get github.com/datadog/orchestrion@latest
> ```

## How it works

The go toolchain's `-toolexec` feature invokes `orchestrion toolexec` with the complete list of arguments for each
toolchain command invocation, allowing `orchestrion` to inspect and modify those before executing the actual command.
This allows `orchestrion` to inspect all the go source files that contribute to the complete application, and to modify
these to include instrumentation code where appropriate. Orchestrion uses [`dave/dst`][dave-dst] to parse and modify the
go source code. Orchestrion adds `//line` directive comments in modified source files to make sure the stack trace
information produced by the final application are not affected by additional code added during instrumentation.

Since the instrumentation may use packages not present in the original code, `orchestrion` also intercepts the standard
go linker command invocations to make the relevant packages available to the linker.

[dave-dst]: https://github.com/dave/dst

### Directive comments

Directive comments are special single-line comments with no space between then `//` and the directive name. These allow
influencing the behavior of Orchestrion in a declarative manner.

#### `//dd:ignore`

The `//dd:ignore` directive instructs Orchestrion not to perform any code changes in Go code nested in the decorated
scope: when applied to a statement, it prevents instrumentations from being added to any component of this statement,
and when applied to a block, or function, it prevents instrumentation from being added anywhere in that block or
function.

This is useful when you specifically want to opt out of instrumenting certain parts of your code, either because it has
already been instrumented manually, or because the tracing is undesirable (not useful, adds too much overhead in a
performance-critical section, etc...).

#### `//dd:span`

Use a `//dd:span` comment before any function or method to create specific spans from your automatically instrumented
code. Spans will include tags described as arguments in the `//dd:span`. In order for the directive to be recognized,
the line-comment must be spelled out with no white space after the `//` comment start.

A function or method annotated with `//dd:span` must receive an argument of type `context.Context` or `*http.Request`.
The context or request is required for trace information to be passed through function calls in a Go program. If this
condition is met, the `//dd:span` comment is scanned and code is inserted in the function preamble (before any other
code).

Span tags are specified as a space-delimited series of `name:value` pairs, or as simple expressions referring to
argument names (or access to fields thereof). All `name:value` pairs are provided as strings, and expressions are
expected to evaluate to strings as well.

```go
//dd:span my:tag type:request name req.Method
func HandleRequest(name string, req *http.Request) {
// ↓↓↓↓ Instrumentation added by Orchestrion ↓↓↓↓
req = req.WithContext(instrument.Report(req.Context(), event.EventStart, "function-name", "HandleRequest", "my", "tag", "type", "request", "name", name, "req.Method", req.Method))
defer instrument.Report(req.Context(), event.EventEnd, "function-name", "HandleRequest", "my", "tag", "type", "request", "name", name, "req.Method", req.Method)
// ↑↑↑↑ End of added instrumentation ↑↑↑↑

// your code here
}
```

## Supported libraries

Orchestrion supports automatic tracing of the following libraries:
Expand Down Expand Up @@ -235,3 +178,12 @@ You can inspect everything Orchestrion is doing by adding the `-work` argument t
the build will emit a `WORK=` line pointing to a working directory that is retained after the build is finished. The
contents of this directory contains all updated source code Orchestrion produced and additional metadata that can help
diagnosing issues.

## More information

Orchestrion's documentation can be found at [datadoghq.dev/orchestrion](https://datadoghq.dev/orchestrion); in
particular:
- the [user guide](https://datadoghq.dev/orchestrion/docs/) provides information about available configuration, and how
to customize the traces produced by your application;
- the [contributor guide](https://datadoghq.dev/orchestrion/contributing/) provides more detailed information about how
orchestrion works and how to contribute new instrumentation to it.
116 changes: 116 additions & 0 deletions _integration-tests/tests/os/lfi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2023-present Datadog, Inc.

//go:build integration

package os

import (
"context"
"fmt"
"net/http"
"os"
"runtime"
"testing"
"time"

"orchestrion/integration/validator/trace"

"github.com/stretchr/testify/require"

"gopkg.in/DataDog/dd-trace-go.v1/appsec/events"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

type TestCase struct {
*http.Server
*testing.T
}

func (tc *TestCase) Setup(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("appsec does not support Windows")
}

t.Setenv("DD_APPSEC_RULES", "./testdata/rasp-only-rules.json")
t.Setenv("DD_APPSEC_ENABLED", "true")
t.Setenv("DD_APPSEC_RASP_ENABLED", "true")
t.Setenv("DD_APPSEC_WAF_TIMEOUT", "1h")
mux := http.NewServeMux()
tc.Server = &http.Server{
Addr: "127.0.0.1:8080",
Handler: mux,
}

mux.HandleFunc("/", tc.handleRoot)

go func() { require.ErrorIs(t, tc.Server.ListenAndServe(), http.ErrServerClosed) }()
}

func (tc *TestCase) Run(t *testing.T) {
tc.T = t
resp, err := http.Get(fmt.Sprintf("http://%s/?path=/etc/passwd", tc.Server.Addr))
require.NoError(t, err)
require.Equal(t, http.StatusForbidden, resp.StatusCode)
}

func (tc *TestCase) Teardown(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

require.NoError(t, tc.Server.Shutdown(ctx))
}

func (tc *TestCase) ExpectedTraces() trace.Spans {
return trace.Spans{
{
Tags: map[string]any{
"name": "http.request",
"resource": "GET /",
"type": "http",
},
Meta: map[string]any{
"component": "net/http",
"span.kind": "client",
},
Children: trace.Spans{
{
Tags: map[string]any{
"name": "http.request",
"resource": "GET /",
"type": "web",
},
Meta: map[string]any{
"component": "net/http",
"span.kind": "server",
"appsec.blocked": "true",
"is.security.error": "true",
},
},
},
},
}
}

func (tc *TestCase) handleRoot(w http.ResponseWriter, _ *http.Request) {

fp, err := os.Open("/etc/passwd")

require.ErrorIs(tc.T, err, &events.BlockingSecurityEvent{})
if events.IsSecurityError(err) { // TODO: response writer instrumentation to not have to do that
span, _ := tracer.SpanFromContext(context.TODO())
span.SetTag("is.security.error", true)
return
}

if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

defer fp.Close()

w.WriteHeader(http.StatusOK)
}
2 changes: 2 additions & 0 deletions _integration-tests/tests/suite.generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 21b6817

Please sign in to comment.