aboutsummaryrefslogtreecommitdiff
path: root/manifests/web.pp
blob: db28e07cc3e09ae26e48cbc5a0bdd82847d749b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# @summary A concourse web node.
# #
# @param service
#   The name of the system service.
#   This service WILL be managed by us.
# @param service_unit
#   Exact unit name (in terms of systemd) of the service.
# @param conf_file
#   Where configuration environment variables will be stored.
#   Currently hard-coded in the service file.
# @param conf_dir
#   Where additional environment files will be stored. Used (at
#   least) by each auth resource.
# @param purge_conf_dir
#   Should the directory mentioned in `conf_dir` be purged. If this
#   is true then decomissioning sub-configurations are done by simply
#   removing that resource.
# @param ensure
# @param cluster
#   Which concourse this web node is part of. An
#   `nginx::resource::upstream::member` resource will be exported,
#   which can be realized by the `concourse::proxy::nginx` resource.
#
# @param peer_address
#   Address to use when connecting this node to the cluster.
#   Should preferably be a private address, since the cluster should
#   only be exposed publicly through the load balancer.
#
#   Despite that, defaults to `$facts['ipaddress']`, since that
#   forces it to work.
#
#   Note that concourse always binds on port 8080, this is currently
#   not configurable.
#
# @param postgres_user
# @param postgres_password
# @param session_signing_key
#
#   Maps to `CONCOURSE_SESSION_SIGNING_KEY`, and is the key private key generated by
#       concourse generate-key -t rsa -f ./session_signing_key
#   That command will also emit a public key, but that key should be discarded since it's unused.
#
#   This key is used for signing and verifying user session tokens.
#
# @param tsa_private_key
#   Private key used to validate SSH connections from workers.
#
#   Generated by
#       concourse generate-key -t ssh -f ./tsa_host_key
#
#   Maps to `CONCOURSE_TSA_HOST_KEY`, and the public part should be passed to each worker.
#
# @param worker_public_keys
# @param key_dir
# @param session_signing_key_file
# @param tsa_host_key_file
# @param tsa_authorized_keys_file
# @param postgres_host
# @param postgres_port
# @param postgres_socket
# @param postgres_database
# @param external_url
#   Publicly facing url of this cluster. Mainly used by the web server to generate proper links.
#
#   For example, 'https://concourse.example.com'
# @param api_max_conns
# @param backend_max_conns
# @param packages
class concourse::web (
  String $cluster                                         = $concourse::default_cluster,
  String $postgres_user                                   = $concourse::configured_clusters[$cluster]['postgres_user'],
  Variant[String, Sensitive[String]] $postgres_password   = $concourse::configured_clusters[$cluster]['postgres_password'],

  Variant[String, Sensitive[String]] $session_signing_key = $concourse::configured_clusters[$cluster]['session_signing_key'],
  Variant[String, Sensitive[String]] $tsa_private_key     = $concourse::configured_clusters[$cluster]['tsa_private_key'],
  Array[String] $worker_public_keys                       = [],

  String $key_dir                                         = '/usr/lib/concourse',
  String $session_signing_key_file                        = "${key_dir}/session_signing_key",
  String $tsa_host_key_file                               = "${key_dir}/tsa_host_key",
  String $tsa_authorized_keys_file                        = "${key_dir}/authorized_worker_keys",

  Optional[String] $peer_address                          = undef,

  Optional[String] $postgres_host                         = undef,
  Optional[String] $postgres_port                         = undef,
  Optional[Stdlib::Unixpath] $postgres_socket             = undef,

  Optional[String] $postgres_database                     = undef,

  String $external_url                                    = "https://${concourse::configured_clusters[$cluster]['external_domain']}",

  Optional[Integer] $api_max_conns                        = undef,
  Optional[Integer] $backend_max_conns                    = undef,

  String $service                                         = 'concourse',
  String $service_unit                                    = "${service}.service",
  Stdlib::Absolutepath $conf_file                            = '/etc/conf.d/concourse',
  Stdlib::Absolutepath $conf_dir                             = '/etc/conf.d/concourse.d',
  Boolean $purge_conf_dir                                 = true,
  Enum['absent', 'present'] $ensure                       = 'present',

  Array[String] $packages                                 = [
    'concourse',
    'concourse-resource-types',
  ],
) {
  include concourse

  ensure_packages($packages, {
      ensure => $ensure,
  })

  $env = {
    'CONCOURSE_SESSION_SIGNING_KEY' => $session_signing_key_file,
    'CONCOURSE_TSA_HOST_KEY'        => $tsa_host_key_file,
    'CONCOURSE_TSA_AUTHORIZED_KEYS' => $tsa_authorized_keys_file,
    'CONCOURSE_POSTGRES_USER'       => $postgres_user,
    'CONCOURSE_POSTGRES_PASSWORD'   => $postgres_password ? {
      String  => $postgres_password,
      default => $postgres_password.unwrap,
    },
    'CONCOURSE_CLUSTER'             => $cluster,
    'CONCOURSE_PEER_ADDRESS'        => $peer_address,
    'CONCOURSE_POSTGRES_HOST'       => $postgres_host,
    'CONCOURSE_POSTGRES_PORT'       => $postgres_port,
    'CONCOURSE_POSTGRES_SOCKET'     => $postgres_socket,
    'CONCOURSE_POSTGRES_DATABASE'   => $postgres_database,
    'CONCOURSE_EXTERNAL_URL'        => $external_url,
    'CONCOURSE_API_MAX_CONNS'       => $api_max_conns,
    'CONCOURSE_BACKEND_MAX_CONNS'   => $backend_max_conns,
  }

  file { $conf_file:
    ensure    => $ensure,
    mode      => '0600',
    show_diff => false,
    content   => epp("${module_name}/env.epp", { 'entries' => $env }),
  }

  file { $conf_dir:
    ensure  => if $ensure == 'present' { 'directory' } else { 'absent' },
    purge   => $purge_conf_dir,
    recurse => true,
    notify  => Service[$service],
  }

  file { $key_dir:
    ensure  => if $ensure == 'present' { 'directory' } else { 'absent' },
    mode    => '0700',
    recurse => true,
    forge   => true,
  }

  file {
    default:
      ensure => $ensure,
      mode   => '0600',
      ;
    $session_signing_key_file:
      content => $session_signing_key,
      ;
    $tsa_host_key_file:
      content => $tsa_private_key,
      ;
  }

  concat { "authorized_workers_key - ${cluster}":
    path           => $tsa_authorized_keys_file,
    warn           => '# File managed by puppet, local changes WILL be overwritten',
    ensure_newline => true,
  }

  $worker_public_keys.each |$key| {
    concat::fragment { sha1($key):
      content => $key,
      target  => "authorized_worker_keys - ${cluster}",
    }
  }

  Concourse::Worker_key <<| cluster == $cluster |>>

  systemd::unit_file { $service_unit:
    ensure => $ensure,
    source => "puppet:///modules/${module_name}/concourse-web.service",
  } ~> service { $service:
    ensure => if $ensure == 'present' { 'running' } else { 'stopped' },
    enable => true,
  }

  # Exported resource
  @@nginx::resource::upstream::member { $trusted['certname']:
    ensure   => $ensure,
    upstream => "concourse - ${cluster}",
    server   => "${peer_address}:8080",
  }
}