Skip to content

Commit

Permalink
feat(challenge)!: split ctfd_challenge in two separate resources
Browse files Browse the repository at this point in the history
Closes #131
Closes #132
  • Loading branch information
pandatix committed Dec 12, 2024
1 parent 3a36970 commit e37a5e2
Show file tree
Hide file tree
Showing 19 changed files with 1,038 additions and 336 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ provider "ctfd" {

We recommend setting the environment variable `CTFD_API_KEY` to enable the provider to communicate with your CTFd instance.

Then, you could use a `ctfd_challenge` resource to setup your CTFd challenge, with for instance the following configuration.
Then, you could use a `ctfd_challenge_standard` resource to setup your CTFd challenges, with for instance the following configuration.
```hcl
resource "ctfd_challenge" "my_challenge" {
name = "My Challenge"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "ctfd_challenges Data Source - terraform-provider-ctfd"
page_title: "ctfd_challenges_dynamic Data Source - terraform-provider-ctfd"
subcategory: ""
description: |-
---

# ctfd_challenges (Data Source)
# ctfd_challenges_dynamic (Data Source)



Expand All @@ -27,19 +27,15 @@ Read-Only:

- `category` (String) Category of the challenge that CTFd groups by on the web UI.
- `connection_info` (String) Connection Information to connect to the challenge instance, useful for pwn or web pentest.
- `decay` (Number)
- `description` (String) Description of the challenge, consider using multiline descriptions for better style.
- `function` (String) Decay function to define how the challenge value evolve through solves, either linear or logarithmic.
- `id` (String) Identifier of the challenge.
- `max_attempts` (Number) Maximum amount of attempts before being unable to flag the challenge.
- `minimum` (Number)
- `name` (String) Name of the challenge, displayed as it.
- `next` (Number) Suggestion for the end-user as next challenge to work on.
- `requirements` (Attributes) List of required challenges that needs to get flagged before this one being accessible. Useful for skill-trees-like strategy CTF. (see [below for nested schema](#nestedatt--challenges--requirements))
- `state` (String) State of the challenge, either hidden or visible.
- `tags` (List of String) List of challenge tags that will be displayed to the end-user. You could use them to give some quick insights of what a challenge involves.
- `topics` (List of String) List of challenge topics that are displayed to the administrators for maintenance and planification.
- `type` (String) Type of the challenge defining its layout, either standard or dynamic.
- `value` (Number)

<a id="nestedatt--challenges--requirements"></a>
Expand Down
47 changes: 47 additions & 0 deletions docs/data-sources/challenges_standard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "ctfd_challenges_standard Data Source - terraform-provider-ctfd"
subcategory: ""
description: |-
---

# ctfd_challenges_standard (Data Source)





<!-- schema generated by tfplugindocs -->
## Schema

### Read-Only

- `challenges` (Attributes List) (see [below for nested schema](#nestedatt--challenges))
- `id` (String) The ID of this resource.

<a id="nestedatt--challenges"></a>
### Nested Schema for `challenges`

Read-Only:

- `category` (String) Category of the challenge that CTFd groups by on the web UI.
- `connection_info` (String) Connection Information to connect to the challenge instance, useful for pwn or web pentest.
- `description` (String) Description of the challenge, consider using multiline descriptions for better style.
- `id` (String) Identifier of the challenge.
- `max_attempts` (Number) Maximum amount of attempts before being unable to flag the challenge.
- `name` (String) Name of the challenge, displayed as it.
- `next` (Number) Suggestion for the end-user as next challenge to work on.
- `requirements` (Attributes) List of required challenges that needs to get flagged before this one being accessible. Useful for skill-trees-like strategy CTF. (see [below for nested schema](#nestedatt--challenges--requirements))
- `state` (String) State of the challenge, either hidden or visible.
- `tags` (List of String) List of challenge tags that will be displayed to the end-user. You could use them to give some quick insights of what a challenge involves.
- `topics` (List of String) List of challenge topics that are displayed to the administrators for maintenance and planification.
- `value` (Number)

<a id="nestedatt--challenges--requirements"></a>
### Nested Schema for `challenges.requirements`

Read-Only:

- `behavior` (String) Behavior if not unlocked, either hidden or anonymized.
- `prerequisites` (List of String) List of the challenges ID.
Original file line number Diff line number Diff line change
@@ -1,88 +1,42 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "ctfd_challenge Resource - terraform-provider-ctfd"
page_title: "ctfd_challenge_dynamic Resource - terraform-provider-ctfd"
subcategory: ""
description: |-
CTFd is built around the Challenge resource, which contains all the attributes to define a part of the Capture The Flag event.
This provider builds a cleaner API on top of CTFd's one to improve its adoption and lifecycle management.
This implementation has support of a more dynamic behavior for its scoring through time/solves thus is different from a standard challenge.
---

# ctfd_challenge (Resource)
# ctfd_challenge_dynamic (Resource)

CTFd is built around the Challenge resource, which contains all the attributes to define a part of the Capture The Flag event.

This provider builds a cleaner API on top of CTFd's one to improve its adoption and lifecycle management.
This implementation has support of a more dynamic behavior for its scoring through time/solves thus is different from a standard challenge.

## Example Usage

```terraform
resource "ctfd_challenge" "http" {
name = "My Challenge"
category = "misc"
description = "..."
value = 500
decay = 100
minimum = 50
state = "visible"
function = "logarithmic"
topics = [
"Misc"
]
tags = [
"misc",
"basic"
]
}
resource "ctfd_flag" "http_flag" {
challenge_id = ctfd_challenge.http.id
content = "CTF{some_flag}"
}
resource "ctfd_hint" "http_hint_1" {
challenge_id = ctfd_challenge.http.id
content = "Some super-helpful hint"
cost = 50
}
resource "ctfd_hint" "http_hint_2" {
challenge_id = ctfd_challenge.http.id
content = "Even more helpful hint !"
cost = 50
requirements = [ctfd_hint.http_hint_1.id]
}
resource "ctfd_file" "http_file" {
challenge_id = ctfd_challenge.http.id
name = "image.png"
contentb64 = filebase64(".../image.png")
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `category` (String) Category of the challenge that CTFd groups by on the web UI.
- `decay` (Number) The decay defines from each number of solves does the decay function triggers until reaching minimum. This function is defined by CTFd and could be configured through `.function`.
- `description` (String) Description of the challenge, consider using multiline descriptions for better style.
- `minimum` (Number) The minimum points for a dynamic-score challenge to reach with the decay function. Once there, no solve could have more value.
- `name` (String) Name of the challenge, displayed as it.
- `value` (Number) The value (points) of the challenge once solved. Internally, the provider will handle what target is legitimate depending on the `.type` value, i.e. either `value` for "standard" or `initial` for "dynamic".
- `value` (Number) The value (points) of the challenge once solved. It is mapped to `initial` under the hood, but displayed as `value` for consistency with the standard challenge.

### Optional

- `connection_info` (String) Connection Information to connect to the challenge instance, useful for pwn, web and infrastructure pentests.
- `decay` (Number) The decay defines from each number of solves does the decay function triggers until reaching minimum. This function is defined by CTFd and could be configured through `.function`.
- `function` (String) Decay function to define how the challenge value evolve through solves, either linear or logarithmic.
- `max_attempts` (Number) Maximum amount of attempts before being unable to flag the challenge.
- `minimum` (Number) The minimum points for a dynamic-score challenge to reach with the decay function. Once there, no solve could have more value.
- `next` (Number) Suggestion for the end-user as next challenge to work on.
- `requirements` (Attributes) List of required challenges that needs to get flagged before this one being accessible. Useful for skill-trees-like strategy CTF. (see [below for nested schema](#nestedatt--requirements))
- `state` (String) State of the challenge, either hidden or visible.
- `tags` (List of String) List of challenge tags that will be displayed to the end-user. You could use them to give some quick insights of what a challenge involves.
- `topics` (List of String) List of challenge topics that are displayed to the administrators for maintenance and planification.
- `type` (String) Type of the challenge defining its layout/behavior, either standard or dynamic (default).

### Read-Only

Expand Down
48 changes: 48 additions & 0 deletions docs/resources/challenge_standard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "ctfd_challenge_standard Resource - terraform-provider-ctfd"
subcategory: ""
description: |-
CTFd is built around the Challenge resource, which contains all the attributes to define a part of the Capture The Flag event.
It is the first historic implementation of its kind, with basic functionalities.
---

# ctfd_challenge_standard (Resource)

CTFd is built around the Challenge resource, which contains all the attributes to define a part of the Capture The Flag event.

It is the first historic implementation of its kind, with basic functionalities.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `category` (String) Category of the challenge that CTFd groups by on the web UI.
- `description` (String) Description of the challenge, consider using multiline descriptions for better style.
- `name` (String) Name of the challenge, displayed as it.
- `value` (Number) The value (points) of the challenge once solved.

### Optional

- `connection_info` (String) Connection Information to connect to the challenge instance, useful for pwn, web and infrastructure pentests.
- `max_attempts` (Number) Maximum amount of attempts before being unable to flag the challenge.
- `next` (Number) Suggestion for the end-user as next challenge to work on.
- `requirements` (Attributes) List of required challenges that needs to get flagged before this one being accessible. Useful for skill-trees-like strategy CTF. (see [below for nested schema](#nestedatt--requirements))
- `state` (String) State of the challenge, either hidden or visible.
- `tags` (List of String) List of challenge tags that will be displayed to the end-user. You could use them to give some quick insights of what a challenge involves.
- `topics` (List of String) List of challenge topics that are displayed to the administrators for maintenance and planification.

### Read-Only

- `id` (String) Identifier of the challenge.

<a id="nestedatt--requirements"></a>
### Nested Schema for `requirements`

Optional:

- `behavior` (String) Behavior if not unlocked, either hidden or anonymized.
- `prerequisites` (List of String) List of the challenges ID.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/ctfer-io/terraform-provider-ctfd
go 1.23.2

require (
github.com/ctfer-io/go-ctfd v0.10.0
github.com/ctfer-io/go-ctfd v0.10.1
github.com/hashicorp/terraform-plugin-docs v0.20.1
github.com/hashicorp/terraform-plugin-framework v1.13.0
github.com/hashicorp/terraform-plugin-go v0.25.0
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZ
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/ctfer-io/go-ctfd v0.10.0 h1:+lBLqde9XNdLB+TzXvJg9I9qkLRA8rYmf9bpjQ2CAUg=
github.com/ctfer-io/go-ctfd v0.10.0/go.mod h1:jNeeXui6iW1jsAfa4D5v6MaK0UF26CtjTRtCqS/PWH4=
github.com/ctfer-io/go-ctfd v0.10.1 h1:Bxr6/qo/h1c0FYFNZv/ej839Hzo5x1VMs0v+Io8ovs8=
github.com/ctfer-io/go-ctfd v0.10.1/go.mod h1:ebgSW8LdP/qtRCpglK4djBp+g6kU5YM98XBZKowiCeY=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -189,8 +189,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
Expand Down
39 changes: 39 additions & 0 deletions provider/challenge_common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package provider

import (
"github.com/ctfer-io/terraform-provider-ctfd/provider/utils"
"github.com/hashicorp/terraform-plugin-framework/types"
)

var (
BehaviorHidden = types.StringValue("hidden")
BehaviorAnonymized = types.StringValue("anonymized")

FunctionLinear = types.StringValue("linear")
FunctionLogarithmic = types.StringValue("logarithmic")
)

type RequirementsSubresourceModel struct {
Behavior types.String `tfsdk:"behavior"`
Prerequisites []types.String `tfsdk:"prerequisites"`
}

func GetAnon(str types.String) *bool {
switch {
case str.Equal(BehaviorHidden):
return nil
case str.Equal(BehaviorAnonymized):
return utils.Ptr(true)
}
panic("invalid anonymization value: " + str.ValueString())
}

func FromAnon(b *bool) types.String {
if b == nil {
return BehaviorHidden
}
if *b {
return BehaviorAnonymized
}
panic("invalid anonymization value, got boolean false")
}
Loading

0 comments on commit e37a5e2

Please sign in to comment.