Skip to content

Commit

Permalink
Allow enabling CWS and CSPM
Browse files Browse the repository at this point in the history
  • Loading branch information
lebauce committed Mar 29, 2022
1 parent 56c0f61 commit f8b6e44
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 3 deletions.
4 changes: 4 additions & 0 deletions attributes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,10 @@
default['datadog']['process_agent']['container_interval'] = nil
default['datadog']['process_agent']['rtcontainer_interval'] = nil

# Cloud Workload Security functionality settings
default['datadog']['security_agent']['cws']['enabled'] = false
default['datadog']['security_agent']['cspm']['enabled'] = false

# System probe functionality settings

# Whether this cookbook should write system-probe.yaml or not.
Expand Down
3 changes: 3 additions & 0 deletions recipes/dd-agent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ def template_vars
# system-probe is a dependency of the agent on Linux or Windows
include_recipe '::system-probe' if system_probe_managed && system_probe_supported

# security-agent is a dependency of the agent on Linux or Windows
include_recipe '::security-agent'

# Installation metadata to let know the agent about installation method and its version
include_recipe '::install_info'

Expand Down
77 changes: 77 additions & 0 deletions recipes/security-agent.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#
# Cookbook:: datadog
# Recipe:: security-agent
#
# Copyright:: 2011-2022, Datadog
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

is_windows = platform_family?('windows')

# Set the correct agent startup action
security_agent_enabled = !is_windows && node['datadog']['security_agent']['cws']['enabled'] || node['datadog']['security_agent']['cspm']['enabled']
security_agent_start = security_agent_enabled ? :start : :stop

#
# Configures security-agent agent
security_agent_config_file = '/etc/datadog-agent/security-agent.yaml'
security_agent_config_file_exists = ::File.exist?(security_agent_config_file)

template security_agent_config_file do
runtime_security_extra_config = {}
if node['datadog']['extra_config'] && node['datadog']['extra_config']['security_agent'] && node['datadog']['extra_config']['security_agent']['runtime_security_config']
node['datadog']['extra_config']['security_agent']['runtime_security_config'].each do |k, v|
next if v.nil?
runtime_security_extra_config[k] = v
end
end

compliance_extra_config = {}
if node['datadog']['extra_config'] && node['datadog']['extra_config']['security_agent'] && node['datadog']['extra_config']['security_agent']['compliance_config']
node['datadog']['extra_config']['security_agent']['compliance_config'].each do |k, v|
next if v.nil?
compliance_extra_config[k] = v
end
end

source 'security-agent.yaml.erb'
variables(
runtime_security_enabled: node['datadog']['security_agent']['cws']['enabled'],
runtime_security_extra_config: runtime_security_extra_config,
compliance_enabled: node['datadog']['security_agent']['cspm']['enabled'],
compliance_extra_config: compliance_extra_config,
)

owner 'root'
group 'dd-agent'
mode '640'

notifies :restart, 'service[datadog-agent-security]', :delayed if security_agent_enabled

# Security agent is not enabled and the file doesn't exists, don't create it
not_if { !security_agent_enabled && !security_agent_config_file_exists }
end

# Common configuration
service_provider = Chef::Datadog.service_provider(node)

service_name = 'datadog-agent-security'

service 'datadog-agent-security' do
service_name service_name
action [security_agent_start]
provider service_provider unless service_provider.nil?
supports :restart => true, :status => true, :start => true, :stop => true
subscribes :restart, "template[#{security_agent_config_file}]", :delayed if security_agent_enabled
end
16 changes: 14 additions & 2 deletions recipes/system-probe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@
is_windows = platform_family?('windows')

# Set the correct agent startup action
cws_enabled = node['datadog']['security_agent']['cws']['enabled']
sysprobe_enabled = if is_windows
node['datadog']['system_probe']['network_enabled']
else
node['datadog']['system_probe']['enabled'] || node['datadog']['system_probe']['network_enabled']
node['datadog']['system_probe']['enabled'] || node['datadog']['system_probe']['network_enabled'] || cws_enabled
end
sysprobe_agent_start = sysprobe_enabled ? :start : :stop

Expand All @@ -47,14 +48,24 @@
end
end

runtime_security_extra_config = {}
if node['datadog']['extra_config'] && node['datadog']['extra_config']['security_agent'] && node['datadog']['extra_config']['security_agent']['runtime_security_config']
node['datadog']['extra_config']['security_agent']['runtime_security_config'].each do |k, v|
next if v.nil?
runtime_security_extra_config[k] = v
end
end

source 'system_probe.yaml.erb'
variables(
enabled: node['datadog']['system_probe']['enabled'],
sysprobe_socket: node['datadog']['system_probe']['sysprobe_socket'],
debug_port: node['datadog']['system_probe']['debug_port'],
bpf_debug: node['datadog']['system_probe']['bpf_debug'],
enable_conntrack: node['datadog']['system_probe']['enable_conntrack'],
extra_config: extra_config
system_probe_extra_config: extra_config,
runtime_security_enabled: cws_enabled,
runtime_security_extra_config: runtime_security_extra_config
)

if is_windows
Expand All @@ -70,6 +81,7 @@
notifies :restart, 'service[datadog-agent-sysprobe]', :delayed if sysprobe_enabled
# since process-agent collects network info through system-probe, enabling system-probe should also restart process-agent
notifies :restart, 'service[datadog-agent]', :delayed if sysprobe_enabled
notifies :restart, 'service[datadog-agent-security]', :delayed if cws_enabled

# System probe is not enabled and the file doesn't exists, don't create it
not_if { !sysprobe_enabled && !system_probe_config_file_exists }
Expand Down
58 changes: 58 additions & 0 deletions spec/security-agent_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
require 'spec_helper'

describe 'datadog::security-agent' do
context 'with CWS enabled' do
cached(:solo) do
ChefSpec::SoloRunner.new(
platform: 'ubuntu',
version: '16.04'
) do |node|
node.name 'chef-nodename' # expected to be used as the hostname in `datadog.yaml`
node.normal['datadog'] = {
'api_key' => 'somethingnotnil',
'agent_major_version' => 6,
'security_agent' => {
'cws' => {
'enabled' => true,
}
},
'extra_config' => {
'security_agent' => {
'runtime_security_config' => {
'activity_dump' => {
'enabled' => true,
}
}
}
}
}
end
end

cached(:chef_run) do
solo.converge(described_recipe) do
solo.resource_collection.insert(
Chef::Resource::Service.new('datadog-agent', solo.run_context))
end
end

it 'security-agent.yaml is created' do
expect(chef_run).to create_template('/etc/datadog-agent/security-agent.yaml')
end

it 'security-agent.yaml contains expected YAML configuration' do
expected_yaml = <<-EOF
compliance_config:
enabled: false
runtime_security_config:
enabled: true
activity_dump:
enabled: true
EOF

expect(chef_run).to(render_file('/etc/datadog-agent/security-agent.yaml').with_content { |content|
expect(YAML.safe_load(content).to_json).to be_json_eql(YAML.safe_load(expected_yaml).to_json)
})
end
end
end
13 changes: 13 additions & 0 deletions templates/default/security-agent.yaml.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<%
## Populate system_probe_config ##
security_agent_config = {
runtime_security_config: {
enabled: @runtime_security_enabled,
}.merge(@runtime_security_extra_config),
compliance_config: {
enabled: @compliance_enabled,
}.merge(@compliance_extra_config),
}
-%>
<%= JSON.parse(security_agent_config.to_json).to_yaml %>
8 changes: 7 additions & 1 deletion templates/default/system_probe.yaml.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ system_probe_config = {
debug_port: @debug_port,
bpf_debug: @bpf_debug,
enable_conntrack: @enable_conntrack,
}.merge(@extra_config),
}.merge(@system_probe_extra_config),
}

if @runtime_security_enabled
system_probe_config['runtime_security_config'] = {
enabled: @runtime_security_enabled
}.merge(@runtime_security_extra_config)
end

# We let the Agent default value take effect if user didn't explicitly
# specify something else than nil for 'network_enabled'
if !node['datadog']['system_probe']['network_enabled'].nil?
Expand Down

0 comments on commit f8b6e44

Please sign in to comment.