Codepen provides embed codes that you can copy from the site and paste into a WYSIWYG.
One variation is a p tag and script, another is an iframe. You can choose one depending on how your editor is configured, and which tags are allowed.
You can open the source editor and paste in these codes.
Both have options like theme and editability that can be set as attributes on the elements.
Here is the result:
Codepen also supports oEmbed.
This lets you convert a url to embed code by retrieving details about the codepen and rendering an iframe.
Drupal core has services to fetch oEmbed info from major providers.
If the service you want to use is on the list, Drupal is already capable of fetching oEmbed info for a given url.
To leverage this as a media type, a hook or OEmbed based MediaSource plugin needs to be implemented to define Codepen as an available source.
Check out mglaman's notes on how to define Codepen as a media type programmatically.
You can do this via a UI using oEmbed Providers.
Create a provider bucket and select CodePen. It will now be available as a media source, so you can create a media type for it.

However, after setting up the media type, trying to add one by url fails.
The issue is mentioned in mglaman's post - the codepen oembed url needs ?format=json.
Here's the fix.
As a media type, it is reusable, can be referenced as a field, and embedded in ckeditor.
However, what is limited is control over the available parameters.
The default oembed source just gets the response and displays the HTML, which in this case is an iframe without the full width p tag from the embed code.
Here's some CSS to add fixes per media type.
What would be ideal is to be able to paste a link, then fill out a form to customize the options, and have that generate the embed code.
This way you leverage oEmbed to load content dynamically, but get the control with the embed code api.
Enter Embeddable Content.
I was able to create a plugin that accepts a codepen url and height parameter, and embeds the iframe response from the oembed API.

Here's a patch to add it to the Codepen module.
More options can be added to the plugin config form, supporting available embed code options.
One big differentiation between solutions is whether you have an embedded media item, or inline embedded content, where values are stored in the text field.
This has implications on reusability display. As media, you can have different display modes. But if there was an easy form to adjust height and width, you may not need to.