diff --git a/.eslintrc.js b/.eslintrc.js index cc65afd..046c765 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,6 +19,7 @@ module.exports = { "react/no-unescaped-entities": ["error", { forbid: [">", "}"] }], "jsx-a11y/click-events-have-key-events": "off", "jsx-a11y/no-static-element-interactions": "off", + "max-len": ["error", { code: 200 }], }, overrides: [ { diff --git a/blog/2025-09-11-ephemeral-ready-for-testing.md b/blog/2025-09-11-ephemeral-ready-for-testing.md new file mode 100644 index 0000000..f089c06 --- /dev/null +++ b/blog/2025-09-11-ephemeral-ready-for-testing.md @@ -0,0 +1,49 @@ +--- +title: Ephemeral Support in OpenTofu +slug: ephemeral-ready-for-testing +--- + +We are excited to announce the availability of Ephemeral and Write-Only features in the latest nightly builds of OpenTofu! + +This is a [highly requested feature](https://github.com/opentofu/opentofu/issues/1996) that we have been hard at work on for a while now. All the necessary components have now been merged and are available in the nightly builds of OpenTofu and will be available in the upcoming 1.11 release. + +:::warning + +Do not test this release on a production project! It is not a stable release! + +::: + +## Downloading the nightly builds + +The nightly builds are available exclusively from the [OpenTofu Nightly Repository](https://nightlies.opentofu.org/nightlies/). Please choose the select the appropriate file for your platform. + +## Ephemeral Overview + +A long-standing issue with OpenTofu and its predecessor has been the storage of sensitive data within the state. Prior to Ephemeral, this data contained everything that OpenTofu knows about the resources it manages. This includes sensitive values, keys, and other secrets that could lead to security incidents if leaked. The introduction of Ephemeral and Write-Only allows for careful configuration to prevent storing this secret data, ensuring that these values only exist within the duration of a single execution of the `tofu` binary. It also allows for transient resources, such as network tunnels, to be made available during specific portions of the OpenTofu Plan/Apply flow. + +### Prior Solutions + +As many seasoned OpenTofu and Terraform authors know, values and attributes can be marked as [Sensitive](/docs/language/functions/sensitive/) to prevent them from being displayed in the CLI. This helps prevent accidental exposure of secrets through CI/CD logs and other mechanisms. It still however stores the plain text data in the state. + +To remedy this, OpenTofu introduced [State and Plan Encryption](/docs/language/state/encryption/). This feature allows you to carefully protect your plan and state data, as well as ensuring that they have not been tampered with in transport. Although the values are still stored within the state and plan, this adds an additional level of security to make it much more difficult for attackers to gain access. It protects the entire state and plan, regardless of how individual resources are configured or marked. Therefore it is still recommended to use state and plan encryption, even after adopting Ephemeral concepts into your workflow. + +### Ephemeral Resources + +[Ephemeral Resources](/docs/main/language/ephemerality/ephemeral-resources/) are entities that only exist during the execution of a single command. They are opened at the beginning of an OpenTofu operation to get their ephemeral value and closed at the end of the operation. These resources can represent anything from keys in a Key Management System to a SSH proxy that is established when the resource is opened. + +The attributes of Ephemeral Resources are marked as `ephemeral` and as such can only be used in [very specific contexts](/docs/main/language/ephemerality/ephemeral-resources/). + +### Write-Only Attributes + +[Write-Only](/docs/main/language/ephemerality/write-only-attributes/) attributes are a special case that has been added to Managed Resources to allow passing ephemeral data into non-ephemeral resources. These attributes can be set in configuration, but their values will never be stored in state or even available as an attribute to be accessed in other portions of the configuration. + +This is geared toward sending ephemeral data, such as passwords and keys, into resources which use and/or manage this data outside of OpenTofu. + + +### Further Reading + +This blog post barely scratches the surface of what is now possible with Ephemeral and Write-Only. Peruse our latest docs for a more [complete overview and in-depth examples](/docs/main/language/ephemerality/)! + +## Providing feedback + +Thank you for taking the time to test this preview release. If you have any feedback, please use [a GitHub issue](https://github.com/opentofu/opentofu/issues/new/choose) or chat with us on the [OpenTofu Slack](https://opentofu.org/slack/). diff --git a/opentofu-repo/main b/opentofu-repo/main index 23d2eaf..79e5070 160000 --- a/opentofu-repo/main +++ b/opentofu-repo/main @@ -1 +1 @@ -Subproject commit 23d2eafe670bb8c4f57e0749e74be134c9003b0d +Subproject commit 79e5070b47805816e7387b925bcb1a174f58d0b0 diff --git a/src/theme/BlogLastPost/index.tsx b/src/theme/BlogLastPost/index.tsx deleted file mode 100644 index e7cc538..0000000 --- a/src/theme/BlogLastPost/index.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import React from "react"; -import PatternBg from "@site/src/components/PatternBg"; -import Button from "@site/src/components/Button"; -import Link from "@docusaurus/Link"; -import { PropBlogPostContent } from "@docusaurus/plugin-content-blog"; - -type BlogLastPostProps = { - item: { - content: PropBlogPostContent; - }; -}; - -export default function BlogLastPost({ item }: BlogLastPostProps) { - const { permalink, title, date, formattedDate, description } = - item.content.metadata; - - return ( -
- -
-
-
-
- - {title} - -
-
- - -

- - {title} - -

-

- {description} -

- -
-
-
-
-
- ); -} diff --git a/src/theme/BlogListItem/index.tsx b/src/theme/BlogListItem/index.tsx index 7c51a43..0e57c60 100644 --- a/src/theme/BlogListItem/index.tsx +++ b/src/theme/BlogListItem/index.tsx @@ -1,5 +1,4 @@ import Link from "@docusaurus/Link"; -import Button from "@site/src/components/Button"; import React from "react"; import { PropBlogPostContent } from "@docusaurus/plugin-content-blog"; @@ -7,29 +6,35 @@ type BlogListItemProps = { item: { content: PropBlogPostContent; }; + isLatestPost?: boolean; }; -export default function BlogListItem({ item }: BlogListItemProps) { +export default function BlogListItem({ + item, + isLatestPost: isLatest = false, +}: BlogListItemProps) { const { permalink, title, date, formattedDate, description } = item.content.metadata; return ( -
+
- - {title} - -
-
- +
+ + {isLatest && ( + + Latest + + )} +
-

+

{description}

- + + Read More → +

+ {item.content.frontMatter.image && ( +
+ + {title} + +
+ )}
); } diff --git a/src/theme/BlogListItems/index.tsx b/src/theme/BlogListItems/index.tsx index d7ab324..6d5c3f9 100644 --- a/src/theme/BlogListItems/index.tsx +++ b/src/theme/BlogListItems/index.tsx @@ -11,9 +11,13 @@ type BlogListItemsProps = { export default function BlogListItems({ items }: BlogListItemsProps) { return ( -
- {items.map((item) => ( - +
+ {items.map((item, index) => ( + ))}
); diff --git a/src/theme/BlogListPage/index.tsx b/src/theme/BlogListPage/index.tsx index d7cbb0b..41782d8 100644 --- a/src/theme/BlogListPage/index.tsx +++ b/src/theme/BlogListPage/index.tsx @@ -5,23 +5,20 @@ import BlogLayout from "@theme/BlogLayout"; import BlogListPaginator from "@theme/BlogListPaginator"; import SearchMetadata from "@theme/SearchMetadata"; import BlogListItems from "@theme/BlogListItems"; -import BlogLastPost from "@theme/BlogLastPost"; import { Props } from "@theme/BlogListPage"; +import PatternBg from "@site/src/components/PatternBg"; export default function BlogListPage(props: Props) { const { metadata, items } = props; const { blogDescription, blogTitle } = metadata; - const lastPost = items[0]; - const otherPosts = items.slice(1); - return ( <> + - - + diff --git a/src/theme/BlogPostItem/index.tsx b/src/theme/BlogPostItem/index.tsx index a9fed51..217d576 100644 --- a/src/theme/BlogPostItem/index.tsx +++ b/src/theme/BlogPostItem/index.tsx @@ -74,9 +74,11 @@ export default function BlogPostItem({ children }: Props) { + { frontMatter.image &&
{title}
+ }