How can I control a CGA screen with an Arduino?
The hsync and vsync signals are just relatively short, negative pulses that reset the CRT's electron beam to the left and top of the screen respectively.

Since CGA was basically just NTSC (AKA RS-170) with separate sync and components, the timing of the pulses should be the same. The hsync would occur about every 63.5 microseconds, and the vsync about every 16.7 milliseconds. The vertical timing should be well within the capabilities of an arduino, but the horizontals might be more challenging.

During the active horizontal scan you'd need to update the luminance according to the horizontal resolution you're designing to. To get 640 pixels, assuming you use about 53 us of the horizontal trace time to allow for HS duration, and margins to make sure your output doesn't run off the edges of the CRT, you need to output a new pixel about every 82 nanos,. Now, 82 ns is (probably) way to fast to get directly from an arduino, but if you employ an external 8-bit shift register, you only have to load that about every 660 ns, i.e., order of half a microsecond. Of course you could opt for 320 pixels and ease the timing further.

If meeting that kind of timing sounds reasonable to you, the exact numbers could easily be had via some light googling. For example, this looks like a pretty good example.