Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⭐️ new OPC UA resource pack #1224

Merged
merged 6 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ activitylog
aks
asns
Auths
autoaccept
autoscaler
backupconfiguration
bigquery
Expand All @@ -27,14 +28,19 @@ hostkeys
iap
iex
ilb
iotedge
ingresstls
loggingservice
managedzone
mcr
messagestoragepolicy
mfs
Mpim
nodepool
oci
opc
opcplc
opcua
Pids
postgre
pushconfig
Expand All @@ -43,11 +49,13 @@ resourcegroup
Sas
serviceprincipals
Snat
sph
spo
sqlserver
sshkeys
toplevel
tpu
uint
vcn
vcns
vdcs
Expand Down
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ lr/build:
./lr go resources/packs/oci/oci.lr
./lr docs yaml resources/packs/oci/oci.lr --docs-file resources/packs/oci/oci.lr.manifest.yaml
./lr docs json resources/packs/oci/oci.lr.manifest.yaml
./lr go resources/packs/opcua/opcua.lr
./lr docs yaml resources/packs/opcua/opcua.lr --docs-file resources/packs/opcua/opcua.lr.manifest.yaml
./lr docs json resources/packs/opcua/opcua.lr.manifest.yaml

lr/release:
go generate .
Expand Down Expand Up @@ -239,6 +242,11 @@ lr/docs/markdown: lr/build
--description "The Oracle Cloud Infrastructure (OCI) resource pack lets you use MQL to query and assess the security of your OCI cloud services." \
--docs-file resources/packs/oci/oci.lr.manifest.yaml \
--output ../docs/docs/mql/resources/oci-pack
./lr markdown resources/packs/opcua/opcua.lr \
--pack-name "OPC UP" \
--description "The OPC-UA resource pack lets you use MQL to query and assess the security of your OPC-UA servers." \
--docs-file resources/packs/opcua/opcua.lr.manifest.yaml \
--output ../docs/docs/mql/resources/opcua-pack

.PHONY: resources
resources: | lr resources/generate resources/test
Expand Down
9 changes: 9 additions & 0 deletions apps/cnquery/cmd/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ func buildCmd(baseCmd *cobra.Command, commonCmdFlags common.CommonFlagsFn, preRu
baseCmd.AddCommand(scanSlackCmd(commonCmdFlags, preRun, runFn, docs))
baseCmd.AddCommand(scanVcdCmd(commonCmdFlags, preRun, runFn, docs))
baseCmd.AddCommand(scanFilesystemCmd(commonCmdFlags, preRun, runFn, docs))
baseCmd.AddCommand(scanOpcUaCmd(commonCmdFlags, preRun, runFn, docs))
}

func localProviderCmd(commonCmdFlags common.CommonFlagsFn, preRun common.CommonPreRunFn, runFn runFn, docs common.CommandsDocs) *cobra.Command {
Expand Down Expand Up @@ -547,3 +548,11 @@ func scanFilesystemCmd(commonCmdFlags common.CommonFlagsFn, preRun common.Common
cmd := common.ScanFilesystemCmd(commonCmdFlags, preRun, wrapRunFn, docs)
return cmd
}

func scanOpcUaCmd(commonCmdFlags common.CommonFlagsFn, preRun common.CommonPreRunFn, runFn runFn, docs common.CommandsDocs) *cobra.Command {
wrapRunFn := func(cmd *cobra.Command, args []string) {
runFn(cmd, args, providers.ProviderType_OPCUA, DefaultAssetType)
}
cmd := common.ScanOpcUACmd(commonCmdFlags, preRun, wrapRunFn, docs)
return cmd
}
17 changes: 17 additions & 0 deletions apps/cnquery/cmd/builder/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -788,3 +788,20 @@ func ScanFilesystemCmd(commonCmdFlags CommonFlagsFn, preRun CommonPreRunFn, runF
commonCmdFlags(cmd)
return cmd
}

func ScanOpcUACmd(commonCmdFlags CommonFlagsFn, preRun CommonPreRunFn, runFn RunFn, docs CommandsDocs) *cobra.Command {
cmd := &cobra.Command{
Use: "opcua",
Short: docs.GetShort("opcua"),
Long: docs.GetLong("opcua"),
Args: cobra.ExactArgs(0),
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlag("endpoint", cmd.Flags().Lookup("endpoint"))
preRun(cmd, args)
},
Run: runFn,
}
commonCmdFlags(cmd)
cmd.Flags().String("endpoint", "", "OPC UA service endpoint")
return cmd
}
15 changes: 15 additions & 0 deletions apps/cnquery/cmd/builder/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,21 @@ func ParseTargetAsset(cmd *cobra.Command, args []string, providerType providers.
case providers.ProviderType_FS:
connection.Backend = providerType
connection.Options["path"] = filepath
case providers.ProviderType_OPCUA:
connection.Backend = providerType

cred := &vault.Credential{
Type: vault.CredentialType_password,
Password: password,
}

if x, err := cmd.Flags().GetString("endpoint"); err != nil {
log.Fatal().Err(err).Msg("cannot parse --endpoint value")
} else if x != "" {
connection.Options["endpoint"] = x
}

connection.Credentials = append(connection.Credentials, cred)
}

parsedAsset.Connections = []*providers.Config{connection}
Expand Down
3 changes: 3 additions & 0 deletions apps/cnquery/cmd/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ This example connects to Microsoft 365 using the PEM formatted certificate:
"filesystem": {
Short: "Scan a mounted file system target.",
},
"opcua": {
Short: "Scan a OPC UA endpoint.",
},
},
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
Expand Down
11 changes: 7 additions & 4 deletions apps/cnquery/cmd/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,16 @@ Provide the recording with mock data as an argument:
`,
},
"vagrant": {
Short: "Scan a Vagrant host.",
Short: "Connect to a Vagrant host.",
},
"terraform": {
Short: "Scan Terraform HCL (files.tf and directories), plan files (json), and state files (json).",
Short: "Connect to Terraform HCL (files.tf and directories), plan files (json), and state files (json).",
},
"ssh": {
Short: "Scan an SSH target.",
Short: "Connect to an SSH target.",
},
"winrm": {
Short: "Scan a WinRM target.",
Short: "Connect to a WinRM target.",
},
"container": {
Short: "Connect to a container, image, or registry.",
Expand Down Expand Up @@ -242,6 +242,9 @@ This example connects to Microsoft 365 using the PKCS #12 formatted certificate:
"filesystem": {
Short: "Connect to a mounted file system target.",
},
"opcua": {
Short: "Connect to a OPC UA endpoint.",
},
},
},
Run: func(cmd *cobra.Command, args []string, provider providers.ProviderType, assetType builder.AssetType) {
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ require (
github.com/google/go-containerregistry v0.12.1
github.com/google/go-github/v49 v49.1.0
github.com/google/uuid v1.3.0
github.com/gopcua/opcua v0.3.13
github.com/gosimple/slug v1.13.1
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/hashicorp/go-hclog v1.2.0
Expand Down Expand Up @@ -172,7 +173,7 @@ require (
github.com/zclconf/go-cty v1.10.0
go.mondoo.com/ranger-rpc v0.0.0-20230328135530-12135c17095f
go.opentelemetry.io/otel v1.14.0
golang.org/x/crypto v0.5.0
golang.org/x/crypto v0.7.0
golang.org/x/net v0.8.0
golang.org/x/oauth2 v0.5.0
golang.org/x/sync v0.1.0
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ=
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gopcua/opcua v0.3.13 h1:33qX6pjZraA65+j7yx7hnDk/M8WMSkbTrJHtIVghTNU=
github.com/gopcua/opcua v0.3.13/go.mod h1:DVDwHvR5lYgO9T4nTn+QxzGl6VQMywgaRgmOH1skBps=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbrhuD+9fLZ4iaAVwhlp5PEhmnBt7yvK2Oy5C1U=
Expand Down Expand Up @@ -1416,8 +1418,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand Down
61 changes: 61 additions & 0 deletions motor/discovery/opcua/resolver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package opcua

import (
"context"
"errors"

"go.mondoo.com/cnquery/motor/asset"
"go.mondoo.com/cnquery/motor/discovery/common"
"go.mondoo.com/cnquery/motor/providers"
opcua_provider "go.mondoo.com/cnquery/motor/providers/opcua"
"go.mondoo.com/cnquery/motor/providers/resolver"
"go.mondoo.com/cnquery/motor/vault"
)

type Resolver struct{}

func (k *Resolver) Name() string {
return "OPC-UA Resolver"
}

func (r *Resolver) AvailableDiscoveryTargets() []string {
return []string{common.DiscoveryAuto, common.DiscoveryAll}
}

func (r *Resolver) Resolve(ctx context.Context, root *asset.Asset, cc *providers.Config, credsResolver vault.Resolver, sfn common.QuerySecretFn, userIdDetectors ...providers.PlatformIdDetector) ([]*asset.Asset, error) {
resolved := []*asset.Asset{}

m, err := resolver.NewMotorConnection(ctx, cc, credsResolver)
if err != nil {
return nil, err
}
defer m.Close()

provider, ok := m.Provider.(*opcua_provider.Provider)
if !ok {
return nil, errors.New("could not create ms OPC UA provider")
}

identifier, err := provider.Identifier()
if err != nil {
return nil, err
}

// detect platform info for the asset
pf, err := m.Platform()
if err != nil {
return nil, err
}

if cc.IncludesOneOfDiscoveryTarget(common.DiscoveryAuto, common.DiscoveryAll) {
resolved = append(resolved, &asset.Asset{
PlatformIds: []string{identifier},
Name: "OPC UA server",
Platform: pf,
Connections: []*providers.Config{cc}, // pass-in the current config
Labels: map[string]string{},
})
}

return resolved, nil
}
5 changes: 3 additions & 2 deletions motor/discovery/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import (
"context"
"strings"

"go.mondoo.com/cnquery/motor/discovery/oci"

"github.com/cockroachdb/errors"
"github.com/rs/zerolog/log"
"go.mondoo.com/cnquery/motor/asset"
Expand All @@ -36,7 +34,9 @@ import (
"go.mondoo.com/cnquery/motor/discovery/mock"
"go.mondoo.com/cnquery/motor/discovery/ms365"
"go.mondoo.com/cnquery/motor/discovery/network"
"go.mondoo.com/cnquery/motor/discovery/oci"
"go.mondoo.com/cnquery/motor/discovery/okta"
"go.mondoo.com/cnquery/motor/discovery/opcua"
"go.mondoo.com/cnquery/motor/discovery/os"
"go.mondoo.com/cnquery/motor/discovery/slack"
"go.mondoo.com/cnquery/motor/discovery/tar"
Expand Down Expand Up @@ -95,6 +95,7 @@ func init() {
providers.ProviderID_SLACK: &slack.Resolver{},
providers.ProviderID_VCD: &vcd.Resolver{},
providers.ProviderID_OCI: &oci.Resolver{},
providers.ProviderID_OPCUA: &opcua.Resolver{},
}
}

Expand Down
3 changes: 3 additions & 0 deletions motor/platform/detector/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package detector

import (
"errors"
"go.mondoo.com/cnquery/motor/providers/opcua"
"runtime"

"go.mondoo.com/cnquery/motor/platform"
Expand Down Expand Up @@ -133,6 +134,8 @@ func (d *Detector) Platform() (*platform.Platform, error) {
return pt.PlatformInfo()
case *oci.Provider:
return pt.PlatformInfo()
case *opcua.Provider:
return pt.PlatformInfo()
case os.OperatingSystemProvider:
var resolved bool
pi, resolved = d.resolveOS(pt)
Expand Down
3 changes: 3 additions & 0 deletions motor/providers/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const (
ProviderID_SLACK = "slack"
ProviderID_VCD = "vcd"
ProviderID_OCI = "oci"
ProviderID_OPCUA = "opc-ua"

// NOTE: its not mapped directly to a transport, it is transformed into ssh
ProviderID_AWS_EC2_INSTANCE_CONNECT = "aws-ec2-connect"
Expand Down Expand Up @@ -84,6 +85,7 @@ var ProviderType_id = map[ProviderType]string{
ProviderType_SLACK: ProviderID_SLACK,
ProviderType_VCD: ProviderID_VCD,
ProviderType_OCI: ProviderID_OCI,
ProviderType_OPCUA: ProviderID_OPCUA,
}

var ProviderType_idvalue = map[string]ProviderType{
Expand Down Expand Up @@ -121,6 +123,7 @@ var ProviderType_idvalue = map[string]ProviderType{
ProviderID_SLACK: ProviderType_SLACK,
ProviderID_VCD: ProviderType_VCD,
ProviderID_OCI: ProviderType_OCI,
ProviderID_OPCUA: ProviderType_OPCUA,
}

func (x ProviderType) Id() string {
Expand Down
Loading